我有一个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 Format,但又想让Hoc本身成为一个功能组件,我该如何解决这种情况?
或者我只是改变
const [selected, setSelected] = useState(f());
到
const [selected, setSelected] = useState(() => f());
你误用了 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自己处理状态,不过不推荐这样做。
对于这种情况,我更倾向于采用以下方法之一。
将 f()
从母体到HOC组件
这是在创建HOC的同时生成init状态的最简单的方法。
使用 useEffect
如果第一次渲染时是空白状态就可以了。
你可以认为
useEffect
如旧didMount
生命周期API。
答案是改变
const [selected, setSelected] = useState(f())。
到
const [selected, setSelected] = useState(() => f())。
而f()无论渲染多少次,都只会调用一次,除了unmount