useState 钩子无法更新地图

时间:2021-03-08 06:30:19

标签: javascript arrays reactjs dictionary react-hooks

我正在使用 useState 钩子来存储地图

    const [optionList, setOptionsList] = useState(new Map([
        [
            uuidv1(), {
                choice: "",
            }
        ]
    ]));

在添加一个新选项时,我调用这个函数

    const handleAddNewOption = () => {
        console.log('reached here');
        optionList.set(uuidv1(), {
            choice: "",
        });
    }

但列表不会在更新时重新呈现

    useEffect(() => {
    console.log("optionList", optionList)    
}, [optionList]);

2 个答案:

答案 0 :(得分:2)

您需要检索条目数组,然后向其中添加新条目,最后构建一个全新的 Map。

const handleAddNewOption = () => {
    console.log('reached here');
    const entries = [
        ...optionList.entries(),
        [
            uuidv1(),
            { choice: "" }
        ]
    ];
    setOptionsList(new Map(entries));
}

您也可以考虑使用 useState 的回调形式,这样您就不必在每次渲染时创建一个新的未使用的地图。

另一个需要考虑的选择是使用由 uuid 索引的对象而不是 Map,如果只是为了便于编码 - 使用 Maps 和 React 比理想情况要复杂一些。

答案 1 :(得分:0)

React 浅层比较旧状态和新状态值以检测是否发生了变化。由于是同一个 Map(不比较 Map 的项),React 会忽略更新。

您可以从旧地图创建一个新地图,然后对其进行更新:

const { useState, useEffect } = React;

const uuidv1 = () => Math.random(); // just for the demo

const Demo = () => {
    
  const [optionList, setOptionsList] = useState(new Map([
    [
      uuidv1(), {
          choice: "",
      }
    ]
  ]));

  const handleAddNewOption = () => {
    console.log('reached here');

    setOptionsList(prevList => {
      const newList = new Map(prevList);

      newList.set(uuidv1(), {
        choice: "",
      });

      return newList;
    });
  };

  useEffect(() => {
    console.log("optionList", JSON.stringify([...optionList]));
  }, [optionList]);

  return (
    <button onClick={handleAddNewOption}>Add</button>
  );
}

ReactDOM.render(
  <Demo />,
  root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>