首页 > 解决方案 > 在 Hook 版本中使用 WrappedComponent 反应 HOC 总是重新初始化状态

问题描述

我有一个 HOC,目前我想将它改造成 Hook 版本,但是我发现它总是呈现

让我们看看这个例子:

const f = ()=> { console.log("init"); return "";}
const hoc = ({someProp = ""}) => WrappedComponent => {
   const HOC = ({...props}) => {
       const [selected, setSelected] = useState(f());
       return <WrappedComponent {...props} setSelected={setSelected}/>
   }
   return HOC;
}

当从 WrappedComponent 触发 setSelected 时,f() 将始终调用

让我们看看另一个例子:

const f = ()=> { console.log("init"); return "";}
const hoc = ({someProp = ""}) => WrappedComponent => {
   class HOC extends Component {
         constructor(props) {
            super(props);
            this.state = {selected: f()}
            this.setSelected = this.setSelected.bind(this);
         }
         setSelected(value) {
            this.setState({selected:value})
        }
        render() {
           return <WrappedComponent {...props} setSelected={this.setSelected}/>

        }
  }

  return HOC;
}

f() 只会调用一次

如果我必须使用 Hoc 格式,但只想让 hoc 本身成为一个功能组件,我该如何解决这个问题?

或者我只是改变

const [selected, setSelected] = useState(f()); 

const [selected, setSelected] = useState(() => f());

标签: reactjsreact-hooks

解决方案


你在滥用useState.

每次 HOC 渲染时,f()都会被调用。

在这里啰嗦一下,也许下面的代码会让你看得更清楚

const hoc = ({someProp = ""}) => WrappedComponent => {
   const HOC = ({...props}) => {
       const state = f(); // Sure, this line would be executed every time.
       const [selected, setSelected] = useState(state);
       ...
   }
  ...
}

我猜您想f()在初始化 Component 时执行以获取 init 状态,然后让 Component 自己处理状态,尽管不建议这样做。

对于这种情况,我更喜欢以下方法之一:

  1. 将结果f()从父组件传递给 HOC 组件

    这是同时创建 HOC 和生成 init 状态的最简单方法

  2. useEffect如果第一次渲染空白状态很好,请使用。

    您可以将useEffect其视为旧的didMount生命周期 API。


推荐阅读