状态更改后 React 功能组件不会更新

Ract functional component doesn't update after state change

我试图在用户选择下拉列表后更新状态,但是,所选选项永远不会改变。查看 gif -- https://recordit.co/KH2Pqn34bp.

我很困惑,理想情况下,在使用 setFilterOptions 更新状态后,它应该使用新值重新渲染该组件,但它并没有发生。谁能帮忙看一下?我在这里错过了什么?非常感谢!

沙盒上的示例代码 -- https://codesandbox.io/s/react-select-default-value-forked-1ybdk?file=/index.js

const SearchFilter = () => {
    const [filterOptions, setFilterOptions] = useContext(SearchFilterContext);  
    let curSort = filterOptions['sortType'] || DEFAULT_SORT_OPTION;
    const handleSortChange = (option) => {
        setFilterOptions(previous => Object.assign(previous, { 'sortType': option }))
    };
    return (
        <span className='filter-container'>
            <Select options={SORT_TYPE_OPTIONS} value={curSort} onChange={handleSortChange}/>
       </span>
    );
};

您没有看到变化的原因是此功能组件只会在看到您的状态发生变化时才重新呈现(基于您的沙箱脚本)。在您使用 Object.assign(previous, { 'sortType': option}) 的那一刻,您正在更改对象中的 sortType 属性 但对象本身没有改变,因此功能组件没有看到变化。

我们可以通过使用 Object.assign({}, previous, { 'sortType': option}) 来解决这个问题,这将创建一个具有先前状态属性和更改后的 sortType 的新对象(Object.assign 的第一个参数是以下对象属性所在的对象将被复制到。如果我们使用一个相当于新对象的空对象)或者我们可以使用扩展运算符并将其替换为 ({...sortType, 'sortType': option}) 这也将创建一个新对象,功能组件将识别为更改状态值。

const handleSortChange = (option) => {
    setFilterOptions(previous => Object.assign({}, previous, { 'sortType': option }))
};

const handleSortChange = (option) => {
    setFilterOptions(previous => ({...previous, 'sortType': option})
};

请记住,这些是浅表对象副本。

您的代码中有几个问题:

  1. 要设置Select组件的默认值,你写了一些不必要的代码。相反,您可以只使用 defaultValue 属性来设置 Select 组件的默认值。

    <Select
       options={OPTIONS}
       defaultValue={OPTIONS[0]}
       onChange={handleSortChange}
    />
    
  2. 您正在直接改变状态。 Object.assign(...) return 是 target 对象。在你的例子中,目标对象是之前的状态。

    不是 return 新状态对象,而是直接改变状态和 return 防止重新渲染的先前状态对象。

    使用spread-syntax,您可以正确更新状态,如下所示:

    const handleSortChange = (option) => {
       setFilterOptions({ ...filterOptions, sortType: option });
    };
    

以下代码修复了您组件中的上述问题:

const SearchFilter = () => {
  const [filterOptions, setFilterOptions] = useState({});

  const handleSortChange = (option) => {
    setFilterOptions({ ...filterOptions, sortType: option });
  };

  return (
    <span className="filter-container">
      <Select
        options={OPTIONS}
        defaultValue={OPTIONS[0]}
        onChange={handleSortChange}
      />
    </span>
  );
};