useReducer代替Redux
步骤:
- 将数据集中在一个store对象
- 将所有操作集中在reducer
- 创建一个Context
- 创建对数据的读写API
- 将第四步的内容放到第三步的Context
- 用Context.Provider将Context提供给所有组件
- 各个组件用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)
})
}