有状态组件和无状态组件
在无状态组件里
- 没有状态
- 没有生命周期
- 没有
this
这就注定,我们所推崇的函数组件,只能做UI展示的功能,涉及到状态的管理与切换,我们不得不用类组件或者redux。
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性(声明周期等)。
启动一个react项目
npx create-react-app my-app cd my-app npm start
一个计数器组件
import React from 'react';
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
export default Example;
useState
纯函数组件没有状态,State Hooks 用于为函数组件引入状态
声明
https://react.docschina.org/docs/hooks-state.html#declaring-a-state-variable
使用
https://react.docschina.org/docs/hooks-state.html#reading-state
使用多个state
https://react.docschina.org/docs/hooks-state.html#tip-using-multiple-state-variables
更新state
https://react.docschina.org/docs/hooks-state.html#updating-state
用State Hooks重写上边的计数器函数
import React, { useState, useEffect } from 'react';
const Example = () => {
// 声明一个叫 “count” 的 state 变量。
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
// 更新count
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Example;
你之前可能把它们叫做“无状态组件”。但现在我们为它们引入了使用 React state 的能力,所以我们更喜欢叫它”函数组件”。
useEffect
Effect Hook 可以让你在函数组件中执行副作用操作
// 类组件
import React from 'react';
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
export default Example;
// 函数组件
import React, { useState, useEffect } from 'react';
const Example = () => {
// 声明一个叫 “count” 的 state 变量。
const [count, setCount] = useState(0);
// 相当于 componentDidMount 和 componentDidUpdate:
useEffect(() => {
// 使用浏览器的 API 更新页面标题
document.title = `You ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Example;
实现comonentDidMounted
https://segmentfault.com/q/1010000017570341
useContext
使用
https://react.docschina.org/docs/hooks-reference.html#usecontext
import React, { useState, useEffect, useContext } from 'react';
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.light);
console.log(ThemeContext, "--ThemeContext--")
function App() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
/**
* 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
* 当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。
*
* 当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,
* 并使用最新传递给 MyContext provider 的 context value 值。
*/
const theme = useContext(ThemeContext);
console.log(theme, "===")
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
export default App;
useReducer
参考
https://www.jianshu.com/p/7e778adec7d1
我们知道,在使用React的过程中,如遇到状态管理,我们一般会用到Redux,而React本身是不提供状态管理的。而useReducer()
为我们提供了状态管理。首先,关于redux我们都知道,其原理是我们通过用户在页面中发起action,从而通过reducer方法来改变state,从而实现页面和状态的通信。而Reducer的形式是(state, action) => newstate
。类似,我们的useReducer()
是这样的。
const [state, dispatch] = useReducer(reducer, initialState)
它接受reducer函数和状态的初始值作为参数,返回一个数组,其中第一项为当前的状态值,第二项为发送action的dispatch函数。下面我们依然用来实现一个计数器。
和redux一样,我们是需要通过页面组件发起action来调用reducer方法,从而改变状态,达到改变页面UI的这样一个过程。所以我们会先写一个Reducer函数,然后通过useReducer()
返回给我们的state和dispatch来驱动这个数据流。思路就是这样,下面我们上代码
import React, { useReducer } from 'react'
const App = () => {
// reducer
const reducer = (state, action) => {
if (action.type === 'add') {
return {
...state,
count: state.count + 1,
}
} else {
return state
}
}
const addcount = () => {
// 派发action
dispatch({
type: 'add'
})
}
/**
* 它接受reducer函数和状态的初始值作为参数,返回一个数组,
* 其中
* 第一项为当前的状态值
* 第二项为发送action的dispatch函数。
*/
const [state, dispatch] = useReducer(reducer, { count: 0 })
return (
<>
<p>{state.count}</p>
<button onClick={addcount}>count++</button>
</>
)
}
export default App