我的 UI 工作正常,直到它使用类组件。现在我将其重构为一个功能组件。
我必须根据从 API 处理程序收到的数据加载 UI。我的用户界面将反射(reflect)房间内相机的状态。每次从房间打开或关闭摄像头时,我都应该从 API apiToGetCameraState
接收新状态。
我希望 registerVideoStateUpdateHandlerWrapper
中存在的 console.log
首次在 UI 加载时打印,并在每次视频状态更改时加载房间。但是,第一次加载 UI 时它不起作用。
这就是我的组件的样子:
const Home: React.FunctionComponent<{}> = React.memo(() => {
const [video, setToggleVideo] = React.useState(true);
const registerVideoStateUpdateHandlerWrapper = React.useCallback(() => {
apiToGetCameraState(
(videoState: boolean) => {
// this log does not show up when the UI is loaded for the first time
console.log(
`Video value before updating the state: ${video} and new state is: ${videoState} `
);
setToggleVideo(videoState);
}
);
}, [video]);
React.useEffect(() => {
//this is getting called when the app loads
alert(`Inside use effect for Home component`);
registerVideoStateUpdateHandlerWrapper ();
}, [registerVideoStateUpdateHandlerWrapper ]);
return (
<Grid>
<Camera
isVideoOn={video}
/>
</Grid>
);
});
当我的代码位于类组件中时,这工作正常。这就是类组件的样子。
class Home extends Component {
registerVideoStateUpdateHandlerWrapper = () => {
apiToGetCameraState((videoState) => {
console.log(`ToggleVideo value before updating the state: ${this.state.toggleCamera} and new state is: ${videoState}`);
this.setStateWrapper(videoState.toString());
})
}
setStateWrapper = (toggleCameraUpdated) => {
console.log("Inside setStateWrapper with toggleCameraUpdated:" + toggleCameraUpdated);
this.setState({
toggleCamera: (toggleCameraUpdated === "true" ) ? "on" : "off",
});
}
constructor(props) {
super(props);
this.state = {
toggleCamera: false,
};
}
componentDidMount() {
console.log(`Inside componentDidMount with toggleCamera: ${this.state.toggleCamera}`)
this.registerVideoStateUpdateHandlerWrapper ();
}
render() {
return (
<div>
<Grid>
<Camera isVideoOn={this.state.toggleCamera} />
</Grid>
);
}
}
我尝试了什么?
- 我尝试删除
registerVideoStateUpdateHandlerWrapper
函数中的useCallback
以及React.useEffect
和registerVideoStateUpdateHandlerWrapper
中的依赖项数组>。它的行为是一样的 - 我尝试更新
React.useEffect
以将registerVideoStateUpdateHandlerWrapper
的代码包含在其中,但仍然没有成功。
最佳答案
将 registerVideoStateUpdateHandlerWrapper()
移动到 useEffect()
回调中,如下所示。如果你想在状态改变时记录之前的状态,你应该使用 functional update避免capturing the previous state through the closure :
const Home = () => {
const [video, setVideo] = useState(false);
useEffect(() => {
console.log('Inside useEffect (componentDidMount)');
const registerVideoStateUpdateHandlerWrapper = () => {
apiToGetCameraState((videoState) => {
setVideo((prevVideo) => {
console.log(`Video value before updating the state: ${prevVideo} and new state is: ${videoState}`);
return videoState;
});
});
};
registerVideoStateUpdateHandlerWrapper();
}, []);
return (
<Grid>
<Camera isVideoOn={video} />
</Grid>
);
};
当您不再实际需要记录以前的状态时,您应该将 registerVideoStateUpdateHandlerWrapper()
简化为:
const registerVideoStateUpdateHandlerWrapper = () => {
apiToGetCameraState((videoState) => {
setVideo(videoState);
});
};
关于javascript - 我可以在功能组件中使用什么来实现与 componentDidMount 相同的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66253812/