最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Component not updating on Map (dictionary) state change using hooks - Stack Overflow

programmeradmin2浏览0评论

I have a child ponent that is supposed to display names based on a visibility filter with checkboxes. I use a dictionary to keep track of the checked state for each name. However, when I update the dictionary the child does not update.

Here is an example:

These are the ponents:

const App = () => {
  const [names, setNames] = useState(seedNames);
  const [hidden, setHidden] = useState(new Map());

  const handleHidden = e => {
    const name = e.target.name;
    const hidden = e.target.checked;

    setHidden(hidden.set(name, hidden));
  };

  return (
    <div className="App">
      <VisibilityFilter
        names={names}
        hidden={hidden}
        handleHidden={handleHidden}
      />
      <DisplayNames names={names} hidden={hidden} />
    </div>
  );
};

const VisibilityFilter = ({ names, hidden, handleHidden }) => {
  return (
    <div>
      {names.map(name => (
        <div key={name}>
          <input
            type="checkbox"
            name={name}
            checked={hidden.get(name)}
            onChange={handleHidden}
            defaultChecked
          />
          <span>{name}</span>
        </div>
      ))}
    </div>
  );
};


const DisplayNames = ({ names, hidden }) => {
  const visibleNames = names.filter(name => !hidden.get(name));

  return (
    <div>
      {visibleNames.map(name => (
        <div key={name}>{name}</div>
      ))}
    </div>
  );
};

I have a child ponent that is supposed to display names based on a visibility filter with checkboxes. I use a dictionary to keep track of the checked state for each name. However, when I update the dictionary the child does not update.

Here is an example: https://codesandbox.io/s/8k39xmxl52

These are the ponents:

const App = () => {
  const [names, setNames] = useState(seedNames);
  const [hidden, setHidden] = useState(new Map());

  const handleHidden = e => {
    const name = e.target.name;
    const hidden = e.target.checked;

    setHidden(hidden.set(name, hidden));
  };

  return (
    <div className="App">
      <VisibilityFilter
        names={names}
        hidden={hidden}
        handleHidden={handleHidden}
      />
      <DisplayNames names={names} hidden={hidden} />
    </div>
  );
};

const VisibilityFilter = ({ names, hidden, handleHidden }) => {
  return (
    <div>
      {names.map(name => (
        <div key={name}>
          <input
            type="checkbox"
            name={name}
            checked={hidden.get(name)}
            onChange={handleHidden}
            defaultChecked
          />
          <span>{name}</span>
        </div>
      ))}
    </div>
  );
};


const DisplayNames = ({ names, hidden }) => {
  const visibleNames = names.filter(name => !hidden.get(name));

  return (
    <div>
      {visibleNames.map(name => (
        <div key={name}>{name}</div>
      ))}
    </div>
  );
};
Share Improve this question edited Mar 22, 2019 at 19:09 Travis S. asked Mar 22, 2019 at 18:59 Travis S.Travis S. 3431 gold badge4 silver badges14 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 11

The use of immutable state is idiomatic to React, it's expected that simple types like plain objects and arrays are used.

Map set returns the same map, while useState supports only immutable states. In case setter function is called with the same state, a ponent is not updated:

setHidden(hidden.set(name, hidden))

The state should be kept immutable:

setHidden(new Map(hidden.set(name, hidden)))

This may introduce some overhead and defy possible benefits of ES6 Map. Unless Map features like strict item order and non-string keys are in demand, it's preferable to use plain object for the same purpose.

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>