从零开始手写redux
全局state的读写
例1.使用Context读写appState
import React, {
useState, useContext } from "react"
import ReactDOM from 'react-dom'
import './style.css'
const appContext = React.createContext(null)
const App = () => {
const [appState, setAppState] = useState({
user: {
name: 'frank', age: 18 }
})
const contextValue = {
appState, setAppState } //封装成一个对象,塞给上下文
return (
<appContext.Provider value={
contextValue}>
<大儿子 />
<二儿子 />
<小儿子 />
</appContext.Provider >
)
}
const 大儿子 = () => <section>大儿子<User /></section>
const 二儿子 = () => <section>二儿子<UserModifier /></section>
const 小儿子 = () => <section>小儿子</section>
const User = () => {
//获取信息
const contextValue = useContext(appContext)
return <div> User:{
contextValue.appState.user.name} </div>
}
const UserModifier = () => {
//修改信息
const {
appState, setAppState } = useContext(appContext);
const onChange = (e) => {
appState.user.name = e.target.value
setAppState({
...appState })
}
return <div>
<input value={
appState.user.name} onChange={
onChange} />
</div>
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
1.setState特点
如果你给的对象是原来那个对象的引用,只要是引用相同,那我直接不变,setState时是不会生效的。
解决方法: 创建一个新的对象,新的对象包含了appState的所有属性
const contextValue = {
appState, setAppState }
const UserModifier = () => {
//修改
const contextValue = useContext(appContext);
onChange(e){
contextValue.appState.user.name = e.target.value
contextValue.setAppState({
...contextValue.appState})
// contextValue.setAppState(contextValue.appState) 错误
}
...
}
reducer的来历
reducer是如何规范state的创建流程的。
目前创建的state特别不规范,它直接修改了原始的state,
我们应该提供一个函数来帮它创建新的state。
const reducer = (state, actionType, actionData) => {
//const createNewState = (state, actionType, actionData) => {
if (actionType === 'updateUser') {
return {
//新的对象
...state,//首先会拷贝user之外的属性
user: {
//创建user
...state.user,
...actionData
}
}
} else {
return state
}
}
const UserModifier = () => {
const {
appState, setAppState } = useContext(appContext);
const onChange = (e) => {
setAppState(createNewState(appState, 'updateUser',
{
name: e.target.value}))
//setAppState(reducer(appState, 'updateUser', {name: e.target.value}))
}
return <div>
<input value={
appState.user.name} onChange={
onChange} />
</div>
}
return的是全新的对象,规范了创建state的过程。
现在把函数名createNewState
改为reducer
,这就是reducer的由来。
不同的是reducer只接受2个参数:将actionType, actionData
统一成一个叫action的东西,它接受一个type和payload{type,payload}
,payload比较麻烦,其实就是data的意思。
const reducer = (state, {
type, payload }) => {
if (type === 'updateUser') {
return {
...state,
user: {
...state.user,
...payload
}
}
} else {
return state
}
}
const UserModifier = () => {
const {
appState, setAppState } = useContext(appContext);
const onChange = (e) => {
setAppState(reducer(appState, {
type: 'updateUser',
payload: {
name: e.target.value } }))
}
return <div>
<input value={
appState.user.name} onChange={
onChange} />
</div>
}
reducer就是用来规范state创建流程的一个函数。
dispatch的来历
如何使用dispatch来规范setState的流程。
先看下我们是如何setState的:
当我们改name、age、group时,每次都要写前面3个单词,既然每次setState都要复制这3份,不如干脆写一个函数 dispatch
。
setAppState(reducer(appState, {
type: 'updateUser',