React 中“默认道具重新渲染”陷阱的状态是什么?

dwj*_*ton 10 javascript reactjs eslint

我正在寻找有关如何处理此问题的规范参考。

如果我有一个如下所示的组件:


const MyComponent = ({ value = [] }) => {
  const [otherValue, setOtherValue] = React.useState([]);

  React.useEffect(() => {
    setOtherValue(value);
  }, [value]);


  return <div> doesn't matter</div>
};
Run Code Online (Sandbox Code Playgroud)

发生的情况是:

  1. value更改时,会触发 useEffect 回调,并调用 setState
  2. setState 会导致重新渲染,如果value为空,则分配默认数组,这是一个对象,因此这又会导致重新渲染。
  3. 无限循环。

解决方案可以是将默认 prop 声明为常量,例如:

const DEFAULT_VALUE = []; 
const MyComponent = ({ value = DEFAULT_VALUE }) => {
  const [otherValue, setOtherValue] = React.useState([]);

Run Code Online (Sandbox Code Playgroud)

我的问题:

对于 React 的每个版本 16、17、18:

  • 这是一个已经解决的问题吗?如果是的话哪个版本解决了?
  • 如果尚未解决,则指向“无法解决”决策的指针。
  • 有 eslint 规则来捕获这个吗?
  • 通常有助于避免此陷阱的任何其他内容。

Ame*_*icA 5

无限循环与 无关ReactJS,因此任何版本都无法修复它。问题又回到了primitive/reference价值观。

当你使用这个时:

const MyComponent = ({ value = [] }) => {
  const [otherValue, setOtherValue] = React.useState([]);

  React.useEffect(() => {
    setOtherValue(value);
  }, [value]); 
Run Code Online (Sandbox Code Playgroud)

即使对于 props 的一个更改,如果下一个valueundefinedjavascript 创建一个新值[]并将其分配给valueReact.useEffect认为它是新的(实际上这种想法是正确的)并尝试获取新的 prop 并与最后一个进行比较以及对于这些操作中的任何一个使用value并且每次它都是新的,因为它的引用是新的。

但是您的解决方案非常棒,对于任何reference type值,我们都必须缓存它,然后使用它来避免一遍又一遍地创建它:

const DEFAULT_VALUE = []; 
const MyComponent = ({ value = DEFAULT_VALUE }) => {
Run Code Online (Sandbox Code Playgroud)

ESLint

有一些插件规则强制开发人员在必需或非必需的 props 中添加默认值,但它们都没有提示您缓存默认 props 的引用类型值。


Art*_*pio 2

您可以使用名为 defaultProps 的属性。使用defaultProps,属性的默认值将成为组件定义的一部分,并且不再在每次渲染时重置,从而防止useEffect的无限循环。所以它会是这样的:

const MyComponent = ({ value }) => {
  const [otherValue, setOtherValue] = React.useState([]);

  React.useEffect(() => {
    setOtherValue(value);
  }, [value]);


  return <div> doesn't matter</div>
};

MyComponent.defaultProps = {
  value: []
};
Run Code Online (Sandbox Code Playgroud)

是的,有一个 lint 规则,但规则是:

为每个非必需 prop 强制执行 defaultProps 定义

所以这并不完全是你想要的,因为它适用于 prop-types 规则,但我认为会对你有所帮助。如果您想了解有关此规则的更多详细信息,参阅描述它的自述文件。