Context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。(有点全局变量的感觉)
//数据提供者
const BatteryContext = createContext();
const OnlineContext = createContext();
class Leaf extends Component{
render() {
return (
<BatteryContext.Consumer>
{
battery => (
<OnlineContext.Consumer>
{
online => <h1>battery: {battery} online: {String(online)}</h1>
}
</OnlineContext.Consumer>
)
}
</BatteryContext.Consumer>
);
}
}
class Middle extends Component {
render(){
return <Leaf/>
}
}
class App extends Component{
state={
battery: 60,
online: false
};
render() {
const {battery, online} = this.state;
return (
<BatteryContext.Provider value={battery}>
<OnlineContext.Provider value={online}>
<button type="button" onClick={()=>{this.setState({battery: battery-1})}}>Press</button>
<button type="button" onClick={()=>{this.setState({online: !online})}}>Switch</button>
<Middle></Middle>
</OnlineContext.Provider>
</BatteryContext.Provider>
);
}
}
contextType
一般一个组件只有一个Context,这个时候可以用contextType来简化代码。官方文档的例子:
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
React.lazy Suspense Error Boundaries
React.lazy 动态加载组件的方式
Suspense 动态加载组件空隙显示的组件
Error Boundaries 错误边界,如果动态加载组件失败显示的组件
PureComponent memo (优化性能的范畴)
PureComponent 和 Component 的区别在于其他组件的setState会不会触发本身的重新render;PureComponent实现 shouldComponentUpdate();以浅层对比 prop 和 state 的方式来实现了该函数。
memo 作用跟 PureComponent 一样,不同的是 PureComponent 用于class组件;memo 用于函数组件,而不适用 class 组件。
useEffect
- 副作用是指绑定事件、网络请求、访问DOM元素这些
- 通常在Mount之后、Update之后、Unmount之前 进行
- 分别对应 componentDidMount componentDidUpdate
useEffect(()=>{
return ()=>{
//回调函数
}
},[])
useEffect第一次调用相当于 componentDidMount,以后的每次执行相当于componentDidUpdate,回调函数会清除上一次effect,相当于 componentWillUnmount

怎么控制 useEffect 多次渲染都会执行呢?第二个参数传递空数组 [] , 可以让 useEffect 只执行一次。
Hooks中使用Context
使用useContext,在函数组件中不能使用contextType了,static只能用在class中。
const CountContext = createContext();
const Counter = ()=>{
const count = useContext(CountContext)
return (
<h1>{count}</h1>
)
}
const App = (props)=>{
const [count, setCount] = useState(0);
return(
<div>
<button type="button" onClick={()=>{setCount(count+1)}}>add</button>
<CountContext.Provider value={count}>
<Counter/>
</CountContext.Provider>
</div>
)
}
Hooks中memo useMemo
memo的使用可以避免组件本身props没有变化而重新渲染的问题;useMemo 中的函数可以在指定的情况下才执行,同时useMemo可以返回函数,这个时候可以用useCallBack
const Counter = React.memo((props)=>{
console.log("Counter render");
return (
<h1 onClick={props.onClick}>{props.count}</h1>
)
});
const App = (props)=>{
const [count, setCount] = useState(0);
const double = useMemo(()=>{
return count * 2;
}, [count===3]);
// const onClick = useMemo(()=>{
// return ()=>{
// console.log('clicked')
// }
// },[])
//等价useMemo
const onClick = useCallback(()=>{
console.log('clicked')
},[])
return(
<div>
<button type="button" onClick={()=>{setCount(count+1)}}>add</button>
<Counter count={double} onClick={onClick}/>
</div>
)
}
Hooks中Ref useRef
- 获取子组件或者DOM节点的句柄,useRef不能用在函数组件中
class Counter extends PureComponent{
speak(){
console.log(`current count is ${this.props.count}`)
}
render() {
const {props} = this;
console.log("Counter render");
return (
<h1 onClick={props.onClick}>{props.count}</h1>
)
}
}
const App = (props)=>{
const [count, setCount] = useState(0);
const double = useMemo(()=>{
return count * 2;
}, [count===3]);
// const onClick = useMemo(()=>{
// return ()=>{
// console.log('clicked')
// }
// },[])
const counterRef = useRef();
const onClick = useCallback(()=>{
console.log('clicked');
console.log(counterRef.current)
counterRef.current.speak();
},[counterRef])
return(
<div>
<button type="button" onClick={()=>{setCount(count+1)}}>add</button>
<Counter ref={counterRef} count={double} onClick={onClick}/>
</div>
)
}
- 渲染周期之间共享数据的存储
const it = useRef();
useEffect(()=>{
it.current = setInterval(()=>{
setCount(count=>count+1)
}, 1000)
}, [])
useEffect(()=>{
if(count>=10){
clearInterval(it.current)
}
});