ReactJS钩子:更新地图值

时间:2020-07-23 22:31:15

标签: reactjs react-hooks

我是reactjs的新手,这就是为什么它对您而言很幼稚。

我需要更新键未知的地图的值。

    CREATE VIEW pg_stat_statements AS SELECT pg_stat_statements.userid,
    pg_stat_statements.dbid,
    pg_stat_statements.queryid,
    pg_stat_statements.query,
    pg_stat_statements.calls,
    pg_stat_statements.total_time,
    pg_stat_statements.min_time,
    pg_stat_statements.max_time,
    pg_stat_statements.mean_time,
    pg_stat_statements.stddev_time,
    pg_stat_statements.rows,
    pg_stat_statements.shared_blks_hit,
    pg_stat_statements.shared_blks_read,
    pg_stat_statements.shared_blks_dirtied,
    pg_stat_statements.shared_blks_written,
    pg_stat_statements.local_blks_hit,
    pg_stat_statements.local_blks_read,
    pg_stat_statements.local_blks_dirtied,
    pg_stat_statements.local_blks_written,
    pg_stat_statements.temp_blks_read,
    pg_stat_statements.temp_blks_written,
    pg_stat_statements.blk_read_time,
    pg_stat_statements.blk_write_time
   FROM pg_stat_statements(true) pg_stat_statements(userid, dbid, queryid, query, calls, total_time, min_time, max_time, mean_time, stddev_time, rows, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, local_blks_hit, local_blks_read, local_blks_dirtied, local_blks_written, temp_blks_read, temp_blks_written, blk_read_time, blk_write_time);;

在单击两个按钮后,我期望在上面的代码中看到的是:

  const App = () => {
    const [storeMap, setStoreMap] = useState(new Map());
    let _tmpMap = new Map();
    return (<>
    {Object.keys({ key1: "hey", key2: "you" }).map((item) => {
          return (
            <button
              value={item}
              key={item}
              onClick={(e) => {
                _tmpMap.set(item, e.target.value);
           
                console.log(..._tmpMap); // {1}
                setStoreMap(_tmpMap);
              }}
            >
              {item}
            </button>
          );
          //   return <i key={item}>KJ </i>;
        })}
  </>)
   
  }

我实际上看到的是按键1 后的 /* {1} */ console.log(..._tmpMap) //i expect this: {key1:"key1" , key2:"key2"} 和按键2

后的{key1:"key1"}

我的问题是:

如何在保留storeMap先前条目的同时更新storeMap?

Here is the code

3 个答案:

答案 0 :(得分:1)

调用setStoreMap时,组件会重新渲染,并且_tmpMap会重新评估为新的Map。您更新的地图属于先前的渲染,无法访问。您希望在渲染之间保留的所有内容都必须处于状态或引用中,因此,您可以执行以下操作:

const App = () => {
    const [storeMap, setStoreMap] = useState(new Map());
    let _tmpMap = useRef(new Map());
    return (<>
    {Object.keys({ key1: "hey", key2: "you" }).map((item) => {
          return (
            <button
              value={item}
              key={item}
              onClick={(e) => {
                _tmpMap.current.set(item, e.target.value);
                setStoreMap(new Map(_tmpMap.current));
              }}
            >
              {item}
            </button>
          );
          //   return <i key={item}>KJ </i>;
        })}
  </>)   
}

但是,通常建议不要将Maps与React一起使用,因为它们是可变的,React将无法得知何时发生了突变。 storeMap会触发重新渲染和效果的唯一方法是,每次更新时都将其设置为新地图。如果您绝对必须使用Map,那么可变引用是React提供的最接近它们的东西。对象是属于React状态的最复杂的事物。 See this thread

答案 1 :(得分:1)

Ciao,here工作代码。如果单击key1key2按钮,则会将元素添加到地图,如果单击show result按钮,则会看到storeMap的值。

答案 2 :(得分:1)

storeMap.set()更新地图,并由setStoreMap设置状态。

React比较新Map和旧Map的引用,在这种情况下,它们具有相同的值。 如果您想让React“知道”更新,则需要将set的副本(而不是旧参考的副本)传递给setStoreMap,您可以通过创建一个新Map来做到这一点。 我相信您可以放弃使用_tmpMap

const App = () => {
    const [storeMap, setStoreMap] = useState(new Map());

    const updateStoreMap = (k, v) => {
        // pass a clone of storeMap
        setStoreMap(new Map(storeMap.set(k, v)));
    };
    
    return (
        <>
            {Object.keys({ key1: 'hey', key2: 'you' }).map((item) => {
                return (
                    <button
                        value={item}
                        key={item}
                        onClick={(e) => {
                            updateStoreMap(item, e.target.value);
                        }}
                    >
                        {item}
                    </button>
                );
                //   return <i key={item}>KJ </i>;
            })}
        </>
    );
};