Как динамически создавать элементы React (material-ui) с выражениями состояния в свойстве - PullRequest
0 голосов
/ 18 марта 2020

Я хочу динамически создавать контекстные меню материалов в функциональном компоненте. Поэтому я использую состояние следующим образом:

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

, где начальное состояние -

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

. После щелчка правой кнопкой мыши по определенным областям я изменяю соответствующее состояние объекта на местоположение события мыши. Следующие меню должны появиться тогда.

  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;
  }

Изменение состояния действительно работает, но меню не отображаются. Насколько я понимаю проблему, строка кода

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

оценивается при создании элементов Menu уже, а не вставляя выражение, делающее элементы управляемыми изменениями состояния. Фактически, у меня есть контекстные меню, работающие на другой странице с реализацией stati c, то есть я жестко кодирую каждое из них вместо того, чтобы создавать их в al oop.

Есть ли способ предотвратить немедленное вычисление свойства open и фактически сохранить желаемое вместо него выражение?

Любая помощь очень ценится!

Приветствия

1 Ответ

1 голос
/ 18 марта 2020

Проблема заключалась в том, что я вложил объекты в состояние. Таким образом, даже не useEffect распознал какие-либо изменения в состоянии. Я решил проблему, используя вместо этого объект состояний следующим образом

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

Теперь все работает просто отлично; также динамически создавая меню:

 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;
  }
...