【问题标题】:How replace componentWillReceiveProps with hooks [duplicate]如何用钩子替换 componentWillReceiveProps [重复]
【发布时间】:2020-03-12 05:56:54
【问题描述】:

我想知道如何使用 useEffect 之类的 componentWillReceiveProps。

我在我的反应应用程序中使用 redux。

所以当状态更新时我有一些 redux 状态,我不想在我的组件中执行某些功能。当我使用类组件时,我是这样做的:

componentWillReceiveProps(nextProps) {
   if (nextProps.Reducer.complete !== this.props.Reducer.complete) {
     someFunc();
   }
}

现在我只使用功能组件和钩子。

现在我的组件是这样的:我正在尝试以这种方式进行操作,但无法正常工作。知道我在哪里弄错了吗?

function Component(props) {
  const Reducer = useSelector(state => state.Reducer);

  const someFunc = () => {
     .....
  }

  useEffect(() => {
    someFunc();
  }, [Reducer.complete]);

}

export default Component;

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    由于someFunc 是效果的依赖项,并且您每次渲染Component 时都会创建someFunc,因此每次都会调用效果,因为您正确添加了依赖项,或者因为您没有添加它而出现异常行为或者你已经使用 eslint 和详尽的 deps 设置了你的开发环境,你的开发环境会警告你,你的效果缺少依赖项。

    为了防止在每次渲染时重新创建someFunc,您可以使用useCallback

    function Component(props) {
      const Reducer = useSelector(state => state.Reducer);
    
      const someFunc = useCallback(() => {
        //  .....
      }, []);
    
      useEffect(() => {
        someFunc(Reducer.complete); //should use the dep
      }, [Reducer.complete, someFunc]);
    }
    

    如果在 someFunc 的主体中使用在 Component 中创建的道具或值,则将 [] 作为依赖项将不起作用,您可以使用 exhaustive deps 来帮助您。

    这是一个对值变化做出反应的效果示例:

    const {
      useCallback,
      useState,
      useEffect,
    } = React;
    
    function Component() {
      const [complete, setComplete] = React.useState(false);
      const [message, setMessage] = React.useState(
        `complete is ${complete}`
      );
    
      const completeChanged = useCallback(complete => {
        console.log(
          'running effect, setting message:',
          complete
        );
        setMessage(`complete is ${complete}`);
      }, []);
      const toggleComplete = useCallback(
        () => setComplete(c => !c),
        []
      );
      useEffect(() => {
        completeChanged(complete); //should use the dep
      }, [complete, completeChanged, setMessage]);
      console.log('rendering:', complete);
      return (
        <div>
          <button onClick={toggleComplete}>
            toggle complete
          </button>
          {message}
        </div>
      );
    }
    
    
    //render app
    ReactDOM.render(
      <Component />,
      document.getElementById('root')
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    【讨论】:

      【解决方案2】:

      好的,所以我假设Reducer 现在是一个对象并且有一个complete key。 尝试在 useEffect 中创建条件。

      useEffect(() => {
        if (Reducer.complete) {
          runThisFunction()
        }
      }, [Reducer.complete, runThisFuntion])
      

      【讨论】:

      • 在 OP 的代码中,他在 Component 中定义了 someFunc,因此在没有 useCallback 的依赖项中添加这一点将对每次渲染产生影响,即使完成没有改变。
      • 我们应该总是用useCallback 包装一个函数吗? @HMR
      • 在这种情况下是有意义的,因为您只想在完成更改时运行效果,而不是在函数更改并且函数每次渲染都更改时运行。当您传递一个用作事件处理程序的函数(如 onClick)时,最好也使用它,它会阻止 React 不必要地重新渲染 DOM 元素。您可以阅读this answer 中的 cmets,以更详细地了解如果您执行 prop={new=&gt;reference}prop={{new:'reference'}} 会发生什么
      【解决方案3】:

      相当于旧的componentWillReceive props 的 react 钩子可以使用 useEffect 钩子来完成,只需指定我们要监听依赖数组中更改的 prop。 试试这个:

      useEffect( () => {
           someFunc()
      }, [props.something, someFunc])
      

      【讨论】:

      • 您缺少依赖项someFunc,但由于它是在Component 中创建的,如果您不使用useCallback 创建someFunc,它将在每个渲染上运行效果
      猜你喜欢
      • 2020-09-18
      • 2020-08-06
      • 2018-11-14
      • 2020-09-24
      • 2021-06-14
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      相关资源
      最近更新 更多