Context API
react组件中经常会遇到这样一种情况,由于组件嵌套层数过多导致state管理复杂,props传递不方便,这个时候你可以使用redux之流来进行状态管理,但是如果只是个别state难以管理,redux可能有点杀鸡用牛刀了,这时你可以考虑试一下context API。
在react官网文档中是这样来介绍context的:
Context provides a way to pass data through the component tree without having to pass props down manually at every level.(Context提供了一种通过组件树传递数据的方法,而无需在每一级手动传递props。)
下面我们一步一步来看一下如何去使用context
- 我们通过React.createContext()创建一个context对象:
const { Provider, Consumer } = React.createContext()
- 然后创建一个返回Provider组件的包装器组件,并添加要从中访问上下文的所有组件作为子组件:
class Container extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
render() {
return (
<Provider value={{
state: this.state
}}>
{this.props.children}
</Provider>
)
}
}
class Calculator extends React.Component {
render() {
return (
<Container>
<Button />
</Container>
)
}
}
Container组件将是一个全局的Provider,您还可以创建较小的context。
- 在Provider中包含的组件内部,使用Consumer组件来使用context:
class Button extends React.Component {
render() {
return (
<Consumer>
{context => <button>{context.state.count}</button>
</Consumer>
)
}
}
4.您还可以将函数作为传递值给Provider,而Consumer可以使用这些函数来更新context的state:
class Container extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
render() {
return (
<Provider value={{
state: this.state,
addHandle : ()=>{this.setState({count: this.state.count+1})}
}}>
{this.props.children}
</Provider>
)
}
}
/**...**/
<Consumer>
{(context) => (
<button onClick={context.addHandle}>
{context.state.count}
</button>
)}
</Consumer>
这样一来,你就可以很好的解决了多层组件套用的问题。
关于context更多的用法,可以参考react官方文档
高阶组件基础应用(HOC)
高阶组件在react中是一个非常有用的概念,它有点类似于javascript中的高级函数,比如说Array.map(),接受函数作为一个参数,在react中,如果一个组件接受一个组件然后返回一个组件,那么这个组件就可以被称为高阶组件。
一般来说,高阶组件经常用来创建高可复用性的代码,举个例子,我们可以给一个组件去给一个组件添加一些方法或者属性,或者是一个redux store。
下面将给出一个最基础的例子:
const withColor = (Element) =>{
return (
(props) => <Element {...props} color="red" />
)
}
withColor是一个组件,它传递一个组件作为参数,返回一个组件并给这个组件设置了color为'red'。
接下来我们使用withColor这个高级组件:
const Button = () => {
return <button>test</button>
}
const ColoredButton = withColor(Button)
最后我们在渲染出ColoredButton组件:
function App() {
return (
<div className="App">
<h1>Hello</h1>
<ColoredButton />
</div>
)
}
这只是一个最基础的高阶组件的示例,但希望在将这些概念应用于更复杂的场景之前,能够对理解高阶组件的要点有所帮助。
Hooks
Hooks是在React 16.7中引入的新特性,它的作用是能够让我们在函数定义的组件中使用state和生命周期事件,使得函数组件有一个处理事件的好方法。
1. 获取state
我们使用useState()API,创建一个新的state变量,并且可以修改它。 useState()接受state项的初始值,并返回一个包含state变量的数组,以及您调用以更改状态的方法。 由于它返回一个数组,我们使用数组解构来访问每个单独的项,如下所示:
import React, { useState } from 'react'
const Counter = () => {
const [count, setCount] = useState(0)
return (
<div>
<p>总数:{count}</p>
<button onClick={() => setCount(count + 1)}>点击+1</button>
</div>
)
}
ReactDOM.render(<Counter />, document.getElementById('app'))
你可以尽可能的调用useState(),来创建你所需要的state变量,而你只需保证在组件的顶层(不在if或任何其他块中)调用它就ok了。
2.使用生命周期函数
在类组件中,您拥有componentDidMount,componentWillUnmount和componentDidUpdate等生命周期函数,这些函数提供了从变量初始化到API调用等等的用例。
在函数式组件中,Hooks提供useEffect()API,它接受函数作为它的参数,在首次渲染组件时运行,在后面每次重新渲染或组件更新时也会运行。React首先会更新DOM,然后调用传递给useEffect()的函数,与旧的componentDidMount和componentDidUpdate有点类似,但是又有所不同,因为这些操作都不会阻止UI渲染,即使是阻塞了代码,这使我们的APP感觉上更快了。
import React,{ useEffect, useState }from 'react'
const CounterWithNameAndSideEffect = () => {
const [count, setCount] = useState(0)
const [name, setName] = useState('Flavio')
useEffect(() => {
console.log(`Hi ${name} you clicked ${count} times`)
})
return (
<div>
<p>
Hi {name} you clicked {count} times
</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
<button onClick={() => setName(name === 'Flavio' ? 'Roger' : 'Flavio')}>
Change name
</button>
</div>
)
}
ReactDOM.render(
<CounterWithNameAndSideEffect />,
document.getElementById('app')
)
如果我们使用useEffect()有点类似于componentWillUnmount的功能应该怎么操作呢?我们可以在传递给useEffect()的函数里再返回一个函数:
useEffect(() => {
console.log(`Hi ${name} you clicked ${count} times`)
return () => {
console.log(`Unmounted`)
}
})
在每次重新渲染/更新时,useEffect()函数都会执行,这时我们可以给useEffect添加第二个参数来告诉React跳过运行,这个参数是一个包含了需要监视的state变量的数组,如果数组中的其中一项发生改变,react将只会重新执行useEffect:
useEffect(
() => {
console.log(`Hi ${name} you clicked ${count} times`)
},
[name, count]
)
有点类似的是,你也可以传递一个空数组,这样的话,React只执行一次useEffect(在挂载时):
useEffect(() => {
console.log(`Component mounted`)
}, [])
3. Hooks规则
以上是Hooks的最基本的用法,理解这些,基本能应付大部分的应用场景,在react官方文档中,定义了Hooks的两条规则:
- 在最顶层调用Hooks
不要在循环,条件或嵌套函数中调用Hook。 相反,始终在React函数的顶层使用Hooks。 通过遵循此规则,您可以确保每次组件呈现时都以相同的顺序调用Hook。 这就是允许React在多个useState和useEffect调用之间正确保留Hook状态的原因。 - 只在react 函数式组件中调用Hooks
不要在普通js函数中调用Hooks,你只能在react函数式组件中调用Hooks或者在普通的Hooks中调用Hooks。
更多详情可以参考Hooks的官方文档
网友评论