一个订阅好友在线的组件我们在DidMount时通过ID订阅了好友的在线状态,为了防止内存泄露,我们需要在WillUnmount清除订阅,但是当组件已显示在friend道具在屏幕上发生变化时会发生什么?我们的组件会继续显示原来的好友状态。这是一个错误。我们还遇到了由于取消订阅时使用错误的好友ID而导致的内存泄漏或崩溃。classFriendStatusextendsReact.Component{constructor(props){super(props);this.state={isOnline:null};this.handleStatusChange=this.handleStatusChange.bind(this);}componentDidMount(){ChatAPI.subscribeToFriendStatus(this.props.friend.id,this.handleStatusChange);}componentWillUnmount(){ChatAPI.unsubscribeFromFriendStatus(this.props.friend.id,this.handleStatusChange);}handleStatusChange(status){this.setState({isOnline:status.isOnline});}render(){if(this.state.isOnline===null){return'Loading...';返回this.state.isOnline?'在线':'离线';}}优化订阅好友为了解决在线组件中props更新导致的BUG,我们需要在DidUpdatecomponentDidMount()中修改订阅}componentDidUpdate(prevProps){//在取??消订阅friend.id之前ChatAPI.unsubscribeFromFriendStatus(prevProps.friend.id,this.handleStatusChange);//订阅新的friend.idChatAPI.subscribeToFriendStatus(this.props.friend.id,this.handleStatusChange);}componentWillUnmount(){ChatAPI.unsubscribeFromFriendStatus(this.props.friend.id,this.handleStatusChange);}EffectHookuseEffect()允许您在函数组件中执行副作用。默认情况下,它将在第一次渲染后和每次更新后执行。如果您熟悉React类生命周期函数,您可以将useEffectHook视为三个函数的组合:componentDidMount、componentDidUpdate和componentWillUnmount。这是React官网最基本的Hooks应用importReact,{useState,useEffect}from'react';functionExample(){const[count,setCount]=useState(0);}//类似于componentDidMount和componentDidUpdate:useEffect(()=>{//使用浏览器API更新文档标题document.title=`Youclicked${count}times`;});return(
你点击了{count}次
setCount(count+1)}>点击我);}为什么需要清除的效果在效果中返回一个函数?这是一种可选的效果清理机制。每个效果都可以返回一个清理函数。这将添加和删除订阅的逻辑保持在一起。它们都是效果的一部分。React什么时候清除effect?React将在卸载组件时执行清理。正如您之前了解到的,效果会在每次渲染时执行。这就是React在执行当前effect之前清理之前effect的原因。从“反应”中导入反应,{useState,useEffect};functionFriendStatus(props){const[isOnline,setIsOnline]=useState(null);useEffect(()=>{functionhandleStatusChange(status){setIsOnline(status.isOnline);}ChatAPI.subscribeToFriendStatus(props.friend.id,handleStatusChange);//指定如何在这个effect之后清理:returnfunctioncleanup(){ChatAPI.unsubscribeFromFriendStatus(props.friend.id,handleStatusChange);};});if(isOnline===null){return'Loading...';返回isOnline?'在线':'离线';现在假设props.friend.id正在更新100->200->300我们不需要具体的代码来处理更新逻辑,因为useEffect会默认处理它。它会在调用新效果之前清除之前的效果。这是基于没有产生之前的Props//Mountwith{friend:{id:100}}propsChatAPI.subscribeToFriendStatus(100,handleStatusChange)变化导致的BUG;//运行第一个效果//更新为{friend:{id:200}}propsChatAPI.unsubscribeFromFriendStatus(100,handleStatusChange);//清除之前的effectChatAPI.subscribeToFriendStatus(200,handleStatusChange);//运行下一个效果//Updatewith{friend:{id:300}}propsStatFromAPI.romunsubscribe(200,handleStatusChange);//清除之前的effectChatAPI.subscribeToFriendStatus(300,handleStatusChange);//运行下一个效果//UnmountChatAPI.unsubscribeFromFriendStatus(300,handleStatusChange);//清除最后一个效果如何跳过一些不需要的Side-effectfunctions按照上一节的思路,每次重新渲染渲染时都执行这些side-effectfunctions显然是不经济的。如何跳过一些不必要的计算?我们只需要将第二个参数传递给useEffect。使用第二个参数告诉react只有当这个参数的值发生变化时才执行我们传递的副作用函数(第一个参数)。useEffect(()=>{document.title=`您点击了${count}次`;},[count]);//只有当count的值发生变化时,才会重新执行`document.title`这句话扩展:如果想执行只运行一次的效果(仅在组件挂载和卸载时),可以通过一个空数组([])作为第二个参数。这告诉React你的效果不依赖于props或state中的任何值,所以它永远不需要重新执行。这不是特例-它仍然遵循依赖数组的工作方式。参考https://react-1251415695.cos-...