目录
- react父子组件的执行顺序
- 1.class组件
- 2.函数组件 hooks无依赖的情况
react父子组件的执行顺序
react版本:17.x,在此版本中完全可以用Hooks去进行开发了,开始先讲class组件,只是为了更好的帮助理解。
在开发项目的过程中,由于项目比较大,拆分组件的结构比较复杂,会涉及到一个组件中下面嵌套了好几级的子级组件,这里就涉及到父子组件中生命周期的执行顺序的问题;
本文主要讲两种情况,class组件和函数组件,讲一下执行常用到的生命周期的执行顺序:
1.class组件
这里涉及到一些react组件的生命周期函数,需要一定的基础,这里就不再赘述,详细可以去看react官方文档,请看代码:
import React from 'react'; | |
const buildClass = (name)=>{ | |
return class extends React.Component{ | |
constructor(props) { | |
super(props); | |
console.log( name + ' constructor'); | |
} | |
UNSAFE_componentWillMount() { | |
console.log( name + ' componentWillMount'); | |
} | |
componentDidMount() { | |
console.log( name + ' componentDidMount'); | |
} | |
componentWillUnmount() { | |
console.log( name + ' componentWillUnmount'); | |
} | |
UNSAFE_componentWillReceiveProps(nextProps) { | |
console.log( name + ' componentWillReceiveProps(nextProps)'); | |
} | |
shouldComponentUpdate(nextProps, nextState) { | |
console.log( name + ' shouldComponentUpdate(nextProps, nextState)'); | |
return true; | |
} | |
UNSAFE_componentWillUpdate(nextProps, nextState) { | |
console.log( name + ' componentWillUpdate(nextProps, nextState)'); | |
} | |
componentDidUpdate(prevProps, prevState) { | |
console.log( name + ' componetDidUpdate(prevProps, prevState)'); | |
} | |
} | |
} | |
class Child extends buildClass('Child'){ | |
render(){ | |
console.log('Child render') | |
return ( | |
<div>child</div> | |
) | |
} | |
} | |
class ClassFn extends buildClass('Parent'){ | |
render(){ | |
console.log('Parent render') | |
return ( | |
<Child /> | |
) | |
} | |
}; | |
export default ClassFn; |
然后在其他组件中去引用ClassFn.tsx这个文件;可以看一下页面在初始化载入ClassFn时生命周期的执行顺序:
这里注意一下Parent就是ClassFn这个组件。
2.函数组件 hooks无依赖的情况
//HooksFn.tsx,以下是此文件对应的代码 | |
import React, { useEffect } from "react"; | |
import ReactDOM from "react-dom"; | |
const Ai = props => { | |
useEffect(() => { | |
console.log("ai组件加载完成"); | |
}); | |
return <div className="ai" />; | |
}; | |
const Home = props => { | |
useEffect(() => { | |
console.log("Home组件加载完成"); | |
}); | |
return ( | |
<div className="home"> | |
<Ai /> | |
</div> | |
); | |
}; | |
function HooksFn() { | |
useEffect(() => { | |
console.log("HooksFn组件加载完成"); | |
}); | |
return ( | |
<div className="App"> | |
<h1>Hello CodeSandbox</h1> | |
<Home /> | |
<h2>Start editing to see some magic happen!</h2> | |
</div> | |
); | |
} | |
export default HooksFn; |
在上面的代码中,注意一下控制台打印出来的顺序是:
ai组件加载完成 => Home组件加载完成 => HooksFn组件加载完成
如下图所示:
此时如果effect的第二个参数有依赖对象时,依然也是先执行的子组件对应的Hook。
子组件的effect函数的有依赖的情况如下:
//HooksFn.tsx | |
import React, { useEffect } from "react"; | |
const Ai = props => { | |
useEffect(() => { | |
console.log("ai组件加载完成"); | |
}, [props.name]); | |
return <div className="ai" />; | |
}; | |
const Home = props => { | |
useEffect(() => { | |
console.log("Home组件加载完成"); | |
}, [props.name]); | |
return ( | |
<div className="home"> | |
<Ai {...props}/> | |
</div> | |
); | |
}; | |
function HooksFn(props) { | |
// Hooks中有依赖的情况 | |
useEffect(() => { | |
console.log("HooksFn组件加载完成"); | |
}, [props.name]); | |
return ( | |
<div className="App"> | |
<h1>Hello CodeSandbox</h1> | |
<Home {...props}/> | |
<h2>Start editing to see some magic happen!</h2> | |
</div> | |
); | |
} | |
export default HooksFn; |
在其他地方饮用水HooksFn这个组件:
import HooksFn from '@/pages/exercise/HooksFn'; | |
<HooksFn name={'12'}/> |
在控制台的顺序如下图:
最近在做项目的时候发现了问题,在进行组件拆分的时候,把其中一个很重要的请求放在了父组件没拆出来,以为会先发送这个请求,结果排到了最后发父组件的请求,我当时就特别纳闷儿,为何会这样了,后来百度了一大堆资料,才发现跟父子组件的执行顺序有关系。但是我就是想让父组件对应的那个请求先发送怎么办?
最后我的解决办法是:
把这个父组件的请求方法放在useLayoutEffect这个Hook中就行了。
在实际的项目开发过程中,确实需要会出现一些场景,需要父组件的执行顺序在子组件前面,这是后一定要注意react中生命周期方法的执行顺序,如果是在项目中用到Hooks组件比较多的情况,可以考虑一下使用useLayoutEffect。