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

Posted

技术标签:

【中文标题】React 功能组件在状态更改后不更新【英文标题】:Ract functional component doesn't update after state change 【发布时间】: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 【参考方案1】:

代码中的几个问题:

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

    <Select
       options=OPTIONS
       defaultValue=OPTIONS[0]
       onChange=handleSortChange
    />
    

    您正在直接改变状态。 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) 不会更改引用... 没问题,很高兴我能帮上忙!

以上是关于React 功能组件在状态更改后不更新的主要内容,如果未能解决你的问题,请参考以下文章

React Context 组件在状态更改时不会更新

React 功能组件中状态更改后组件未重新渲染

React 功能组件在重新挂载后停止渲染状态更改

根据父状态更新子状态 react 功能组件

警告:无法对未安装的组件执行 React 状态更新。在功能组件中

React hooks 功能组件防止在状态更新时重新渲染