0

I want to dynamically create material-ui context menus within a functional component. Therefore, I use a state as follows

 let legendContextMenuStatesObject = {};
  for (let key of keys) {
    legendContextMenuStatesObject[key] = initialState;
  }
  const [legendContextMenuStates, setLegendContextMenuStates] = useState(
    legendContextMenuStatesObject
  );

where the initial state is

 const initialState = {
  mouseX: null,
  mouseY: null
};

Upon right clicking on certain areas I change the corresponding state Object to the mouse event location. The following menus are supposed to pop up then.

  function contextMenus(keys) {
    console.log(keys);
    const menues = [];
    for (let key of keys) {
      menues.push(
        <Menu
          keepMounted
          open={legendContextMenuStates[key].mouseY !== null}
          onClose={props.onClose}
          anchorPosition={
            legendContextMenuStates[key].mouseY !== null &&
            legendContextMenuStates[key].mouseX !== null
              ? {
                  top: legendContextMenuStates[key].mouseY,
                  left: legendContextMenuStates[key].mouseX
                }
              : undefined
          }
          anchorReference="anchorPosition"
          TransitionComponent={Fade}
        >
          <MenuItem onClick={event => handleClickLegendContextMenu(event, key)}>
            Line style
          </MenuItem>
        </Menu>
      );
    }
    return menues;
  }

The state change actually works, but the menus do not appear. As far as I understand the problem, the line of code

open={legendContextMenuStates[key].mouseY !== null}

Is evaluated when creating the Menu elements already rather than inserting the expression making the elements controllable by state changes. In fact, I got the context menus working on a different page with a static implementation, meaning I hard code each one instead of creating them in a loop.

I there a way to prevent the open property from being evaluated immediately and actually keeping the expression I want instead?

Any help is much appreciated!

Cheers

1 Answer 1

1

The problem was that I nested Objects within the state. That way not even useEffect recognized any changes in state. I solved the problem by using an object of states instead as follows

 let legendContextMenuStates = {};
  for (let key of keys) {
    legendContextMenuStates[key] = useState(initialState);
  }

Now everything works just fine; also creating the menus dynamically:

 function contextMenus() {
    const menus = [];
    for (let key of keys) {
      menus.push(
        <Menu
          keepMounted
          open={legendContextMenuStates[key][0].mouseY !== null}
          onClose={() => {
            legendContextMenuStates[key][1](initialState);
          }}
          anchorPosition={
            legendContextMenuStates[key][0].mouseY !== null &&
            legendContextMenuStates[key][0].mouseX !== null
              ? {
                  top: legendContextMenuStates[key][0].mouseY,
                  left: legendContextMenuStates[key][0].mouseX
                }
              : undefined
          }
          anchorReference="anchorPosition"
          TransitionComponent={Fade}
        >
          <MenuItem onClick={event => handleClickLegendContextMenu(event, key)}>
            Color
          </MenuItem>
          <MenuItem onClick={event => handleClickLegendContextMenu(event, key)}>
            Line style
          </MenuItem>
          <MenuItem onClick={event => handleClickLegendContextMenu(event, key)}>
            Line width
          </MenuItem>
          <MenuItem onClick={event => handleClickLegendContextMenu(event, key)}>
            Curve style
          </MenuItem>
        </Menu>
      );
    }
    return menus;
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.