【问题标题】:Ract functional component doesn't update after state changeReact 功能组件在状态更改后不更新
【发布时间】:2021-03-19 00:57:41
【问题描述】:

我试图在用户选择下拉列表后更新状态,但是,选择的选项永远不会改变。见 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>
    );
};

【问题讨论】:

  • 你能提供一个最小的、可重现的例子吗?我的猜测是您没有在 Select 组件中使用 onChange 属性。
  • @Yousaf 我试图在沙盒上得到这个——codesandbox.io/s/react-select-default-value-forked-1ybdk?file=/…,希望这会有所帮助。
  • @Yousaf 你能解释一下关于不使用onChange prop 的更多信息吗?因为handleSortChange基本上就是onChange方法,里面包含setFilterOptions

标签: reactjs react-hooks use-state use-context


【解决方案1】:

代码中的几个问题:

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

    <Select
       options={OPTIONS}
       defaultValue={OPTIONS[0]}
       onChange={handleSortChange}
    />
    
  2. 您正在直接改变状态。 Object.assign(...) 返回 target 对象。在您的情况下,目标对象是以前的状态。

    您不是返回新的状态对象,而是直接改变状态并返回防止重新渲染的前一个状态对象。

    使用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>
  );
};

【讨论】:

    【解决方案2】:

    您没有看到更改的原因是此功能组件只会在看到您的状态发生更改时重新渲染(基于您的沙盒脚本)。在您使用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})
    };
    

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

    【讨论】:

    • 非常感谢,你拯救了我的一天!!我不知道Object.assign(previous, { 'sortType': option}) 不会更改引用...
    • 没问题,很高兴我能帮上忙!
    猜你喜欢
    • 2020-08-12
    • 2021-07-25
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 2019-12-29
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多