为啥我不能在组件道具中使用内联函数?可以举个例子详细解释一下吗?失去所有状态是啥意思?

Posted

技术标签:

【中文标题】为啥我不能在组件道具中使用内联函数?可以举个例子详细解释一下吗?失去所有状态是啥意思?【英文标题】:Why I can not use inline function in component prop? Can you explain in detail by giving an example? What means saying losing all state?为什么我不能在组件道具中使用内联函数?可以举个例子详细解释一下吗?失去所有状态是什么意思? 【发布时间】:2021-12-01 09:27:24 【问题描述】:

注意:component 属性接受组件,而不是渲染函数。不要传递内联函数(例如 component=() => ),否则当父组件重新渲染时,您的组件将卸载并重新安装丢失所有状态。请参阅传递其他道具以获取替代方案。

来自模拟器的警告。 enter image description here

function HomeScreen(props: Object) 
  return (
    <Navigator initialRouteName="Empty1">
      <Screen
        name="Empty1"
        component=() => 
          return (
            <View>
              <Text>Example Text</Text>
            </View>
          );
        
      />
      <Screen name="Home1" component=HomeScreen1 />
    </Navigator>
  );

【问题讨论】:

“失去所有状态是什么意思?”你知道在 React 应用程序的上下文中什么是“状态”吗?因为如果没有,我建议从basic tutorials开始。 感谢您的建议。 【参考方案1】:

它警告您每次重新渲染屏幕时都会重新渲染组件。这是因为每次评估组件 arg 时,它都会返回一个新的内联函数。 (道具每次都会改变,因此它必须总是重新渲染)

对同一个内联函数求值两次会产生不同的对象。 例如。

let funcs = []
for (let i =0 ; i<2; i++) 
  funcs.push(() => 1)

funcs[0] == funcs[1]
>>> false

您可以包装 this is useCallback 以获得仅在需要时更新的稳定函数(在您的情况下永远不会,因为它不捕获任何状态)。 More on hooks here

function HomeScreen(props: Object) 
  let component = useCallback(() => 
    return (
      <View>
        <Text>Example Text</Text>
      </View>
    );
  , [] // no dependencies. This lambda will only be evaluated once.
  );
  return (
    <Navigator initialRouteName="Empty1">
      <Screen
        name="Empty1"
        component=component
      />
      <Screen name="Home1" component=HomeScreen1 />
    </Navigator>
  );

或者由于这个函数不依赖于任何有状态的东西,你也可以在这个文件的顶部全局声明它。

let component = () => 
    return (
      <View>
        <Text>Example Text</Text>
      </View>
    );
  ;

function HomeScreen(props: Object) 
    return (
    <Navigator initialRouteName="Empty1">
      <Screen
        name="Empty1"
        component=component
      />
      <Screen name="Home1" component=HomeScreen1 />
    </Navigator>
  );

【讨论】:

【参考方案2】:

你需要了解隐藏在 JSX 语法背后的东西。

当你使用&lt;SomeComponent/&gt; 时,它会被添加到 React 虚拟 DOM 并一直存在,直到树发生变化并且必须卸载组件。它在重新渲染后仍然存在,DOM 正在更新,但组件仍然存在。

当您使用() =&gt; &lt;SomeComponent /&gt; 时,此组件在每次重新渲染父组件时都是一个新对象。如果它有状态(通过 setState 钩子),它将被重新初始化。如果它在useEffect(() =&gt; , []) 钩子中有一些代码,它将被再次调用。

【讨论】:

以上是关于为啥我不能在组件道具中使用内联函数?可以举个例子详细解释一下吗?失去所有状态是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能将此信息从一个反应组件推送到另一个?

当组件中有解构赋值时,为啥默认道具不能防止 TypeError?

为啥我不能内联调用 res.json?

为啥我不能在 react native 中以编程方式添加道具?

为啥我不能在我的类中内联函数? [复制]

为啥不能根据道具反应设置初始状态