React的Hooks2——useReducer
是用来规范创建state的创建流程的。
文档中其实是这么说的:是useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
代码要分四步走:
1. 创建初始值initialState
2. 创建所有操作reducer(state,action)
3. 传给useReducer,得到读和写API
4. 调用写({type:"操作类型"})
const initial = {
n:0
}
const reducer = (state,action)=>{
if(action.type==='add'){
return {n:state.n+action.number}
}else if(action.type==="mult"){
return {n:state.n*action.number}
}else{
throw new Error('unknown type')
}
}
function App(){
const [state, dispatch] = useReducer(reducer, initial)
const {n} = state
const onClick=()=>{
dispatch({type:'add',number:1})
}
const onClick2=()=>{
dispatch({type:'mult',number:2})
}
return(
<div className="App">
<h1>n:{n}</h1>
<button onClick={onClick}>+1</button>
<button onClick={onClick2}>*2</button>
</div>
)
}
useReducer代替Redux:
步骤:
1. 将数据几集中在一个store对象
2. 将所有操作集中在reducer
3. 创建一个Context
4. 创建对数据的读写API
5. 将第四步的内容放到第三步的Context
6. 用Context.Provider将Context提供给所有组件
7. 各个组件用useContext获取读写API
import React, { createContext,useReducer,useContext,useEffect } from 'react';
import ReactDOM from 'react-dom';
//1. 将数据几种在一个store对象
const store = {
user: null,
books: null,
movies: null
}
//2.将所有操作集中在reducer
const reducer = (state,action) => {
switch(action.type){
case 'setUser':
return {...state,user:action.user}
case 'setBooks':
return {...state,books:action.books}
case 'setMovies':
return {...state,movies:action.movies}
default:
throw new Error()
}
}
//3. 创建一个Context
const Context = createContext(null)
function App(){
//4. 创建对数据的读写API
const [state, dispatch] = useReducer(reducer, store)
return(
// 第一个花括号表示里面的是JS内容,里面的花括号代表是对象,只是使用ES6的语法缩写了
//5. 将第四步的内容放到第三步的Context 6. 用Context.Provider将Context提供给所有组件
<Context.Provider value = {{state,dispatch}}>
<div>
<User />
<hr />
<Books />
<Movies />
</div>
</Context.Provider>
)
}
function User(){
//7. 各个组件用useContext获取读写API
const {state,dispatch} = useContext(Context)
//useEffe第二个参数是空[]时,表示只会渲染一次
useEffect(() => {
ajax("/user").then(user=>{
dispatch({type:"setUser",user:user})
})
}, [])
return(
<div>
<h1>个人信息</h1>
<div>name:{state.user?state.user.name:""}</div>
</div>
)
}
function Books(){
const {state,dispatch} = useContext(Context)
useEffect(() => {
ajax("/books").then(books=>{
dispatch({type:"setBooks",books:books})
})
}, [])
return(
<div>
<h1>我的书籍</h1>
<ol>
{state.books?state.books.map(book=><li key={book.id}>{book.name}</li>):"加载中"}
</ol>
</div>
)
}
function Movies(){
const {state,dispatch} = useContext(Context)
useEffect(() => {
ajax("/movies").then(movies=>{
dispatch({type:"setMovies",movies:movies})
})
}, [])
return(
<div>
<h1>我的电影</h1>
<ol>
{state.movies?state.movies.map(movie=><li key={movie.id}>{movie.name}</li>):"加载中"}
</ol>
</div>
)
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />,rootElement)
function ajax(path){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(path==="/user"){
resolve({
id:1,
name:"lu"
})
}else if(path==="/books"){
resolve([
{
id:1,
name:"JavaScript高级程序设计"
},
{
id:2,
name:"JavaScript精粹"
}
])
}else if(path==="/movies"){
resolve([
{
id:1,
name:"送你一朵小红花"
},
{
id:2,
name:"美人鱼"
}
])
}
},2000)
})
}