当前位置: 首页 > news >正文

可以做图片视频的网站郑州网站建设修改

可以做图片视频的网站,郑州网站建设修改,五力合一营销型网站建设系统,南宁网站建设接单useReducer usereducer 相当于 复杂的 useState 当状态更新逻辑较复杂时可以考虑使用 useReducer。useReducer 可以同时更新多个状态#xff0c;而且能把对状态的修改从组件中独立出来。 相比于 useState#xff0c;useReducer 可以更好的描述“如何更新状态”。例如#…useReducer usereducer 相当于 复杂的 useState 当状态更新逻辑较复杂时可以考虑使用 useReducer。useReducer 可以同时更新多个状态而且能把对状态的修改从组件中独立出来。 相比于 useStateuseReducer 可以更好的描述“如何更新状态”。例如组件负责发出行为useReducer 负责更新状态。 好处是让代码逻辑更清晰代码行为更易预测。 1. useReducer 的语法格式 useReducer 的基础语法如下 const [state, dispatch] useReducer(reducer, initState, initAction?)其中 1. reducer 是一个函数类似于 (prevState, action) newState。形参 prevState 表示旧状态形参 action 表示本次的行为返回值 newState 表示处理完毕后的新状态。 2. initState 表示初始状态也就是默认值。 3. initAction 是进行状态初始化时候的处理函数它是可选的如果提供了 initAction 函数则会把 initState 传递给 initAction 函数进行处理initAction 的返回值会被当做初始状态。 4. 返回值 state 是状态值。dispatch 是更新 state 的方法让他接收 action 作为参数useReducer 只需要调用 dispatch(action) 方法传入的 action 即可更新 state。 2. 定义组件的基础结构 定义名为 Father 的父组件如下 import React from react// 父组件 export const Father: React.FC () {return (divbutton修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }定义名为 Son1 和 Son2 的两个子组件如下 // 子组件1 const Son1: React.FC () {return div classNameson1/div }// 子组件2 const Son2: React.FC () {return div classNameson2/div }在 index.css 中添加对应的样式 .father {display: flex;justify-content: space-between;width: 100vw; }.son1 {background-color: orange;min-height: 300px;flex: 1;padding: 10px; }.son2 {background-color: lightblue;min-height: 300px;flex: 1;padding: 10px; }3. 定义 useReducer 的基础结构 1、按需导入 useReducer 函数 import React, { useReducer } from react2、定义初始数据 const defaultState { name: liulongbin, age: 16 }3、定义 reducer 函数它的作用是根据旧状态进行一系列处理最终返回新状态 // 第一个参数永远是上一次的旧状态 const reducer (prevState) {// 首次进入页面 不会触发 reducer 函数执行console.log(触发了 reducer 函数)// 必须向外返回一个处理好的新状态 return prevState }4、在 Father 组件中调用 useReducer(reducerFn, 初始状态) 函数并得到 reducer 返回的状态 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state] useReducer(reducer, defaultState)console.log(state)return (divbutton修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }5、为 reducer 中的 initState 指定数据类型 // 定义状态的数据类型 type UserType typeof defaultStateconst defaultState { name: liulongbin, age: 16 }// 给 initState 指定类型为 UserType const reducer (prevState: UserType) {console.log(触发了 reducer 函数)return prevState }6、接下来在 Father 组件中使用 state 时就可以出现类型的智能提示啦 // 父组件 export const Father: React.FC () {const [state] useReducer(reducer, defaultState)console.log(state.name, state.age)return (divbutton修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }4. 使用 initAction 处理初始数据 定义名为 initAction 的处理函数如果初始数据中的 age 为小数、负数、或 0 时对 age 进行非法值的处理 const initAction (initState: UserType) {// 把 return 的对象作为 useReducer 的初始值return { ...initState, age: Math.round(Math.abs(initState.age)) || 18 } }在 Father 组件中使用步骤1声明的 initAction 函数如下 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state] useReducer(reducer, defaultState, initAction)// 省略其它代码... }在定义 defaultState 时为 age 提供非法值可以看到非法值在 initAction 中被处理掉了。 5. 在 Father 组件中点击按钮修改 name 的值 1. 错误示范 不要像 vue 响应式数据一样直接通过 state.name escook 去修改 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state] useReducer(reducer, defaultState, initAction)console.log(state)const onChangeName () {// 注意这种用法是错误的因为不能【直接修改 state 的值】// 因为存储在 useReducer 中的数据都是“不可变”的// 要想修改 useReducer 中的数据必须触发 【reducer】 函数的重新计算// 根据 reducer 形参中的旧状态对象initState经过一系列处理返回一个“全新的”状态对象state.name escook}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefatherSon1 /Son2 //div/div) }2. 正确的操作 为了能够触发 reducer 函数的重新执行我们需要在调用 useReducer() 后接收返回的 dispatch 函数。示例代码如下 // Father 父组件 const [state, dispatch] useReducer(reducer, defaultState, initAction)在 button 按钮的点击事件处理函数中调用 dispatch() 函数从而触发 reducer 函数的重新计算 // Father 父组件 const onChangeName () { dispatch() }点击 Father 组件中如下的 button 按钮 button onClick{onChangeName}修改 name 的值/button会触发 reducer 函数的重新执行并打印 reducer 中的 console.log()代码如下 const reducer (prevState: UserType) {console.log(触发了 reducer 函数)return prevState }3. 调用 dispatch 传递参数给 reducer 在 Father 父组件按钮的点击事件处理函数 onChangeName 中调用 dispatch() 函数并把参数传递给 reducer 的第2个形参代码如下 const onChangeName () {// 注意参数的格式为 { type, payload? }// 其中// type 的值是一个唯一的标识符用来【指定本次操作的类型】一般为大写的字符串// payload 是本次操作需要用到的数据为可选参数。在这里payload 指的是把用户名改为字符串 刘龙彬dispatch({type: UPDATE_NAME, payload: 刘龙彬}) }修改 reducer 函数的形参添加名为 action 的第2个形参用来接收 dispatch 传递过来的数据 const reducer (prevState: UserType, action) {// 打印 action 的值终端显示的值为// {type: UPDATE_NAME, payload: 刘龙彬}console.log(触发了 reducer 函数, action)return prevState }在 reducer 中根据接收到的 action.type 标识符决定进行怎样的更新操作最终 return 一个计算好的新状态。示例代码如下 const reducer (prevState: UserType, action) {console.log(触发了 reducer 函数, action)// return prevStateswitch (action.type) {// 如果标识符是字符串 UPDATE_NAME则把用户名更新成 action.payload 的值// 最后一定要返回一个新状态因为 useReducer 中每一次的状态都是“不可变的”case UPDATE_NAME:return { ...prevState, name: action.payload } // 解除引用赋予新对象// 兜底操作// 如果没有匹配到任何操作则默认返回上一次的旧状态default:return prevState} }4、为 action 指定类型 在上述的 switch...case... 代码期间没有 TS 的类型提示这在大型项目中是致命的。因此我们需要为 reducer 函数的第2个形参 action 指定操作的类型 // 1. 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string }// 2. 为 action 指定类型为 ActionType const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, action)// 3. 删掉之前的代码再重复编写这段逻辑的时候会出现 TS 的类型提示非常 Niceswitch (action.type) {case UPDATE_NAME:return { ...prevState, name: action.payload }default:return prevState} }同时在 Father 组件的 onChangeName 处理函数内调用 dispatch() 时也有了类型提示 const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 }) }注意在今后的开发中正确的顺序是 ​ 1、先定义 ActionType 的类型 ​ 2、修改 reducer 中的 switch...case... 逻辑 ​ 3、在组件中调用 dispatch() 函数这样能够充分利用 TS 的类型提示。 6. 把用户信息渲染到子组件中 1、在 Father 父组件中通过jsx展开语法把 state 数据对象绑定为 Son1 和 Son2 的 props 属性 // 父组件 export const Father: React.FC () {const [state, dispatch] useReducer(reducer, defaultState, initAction)const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 })}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefather!-- 通过 props 的数据绑定把数据传递给子组件 --Son1 {...state} /Son2 {...state} //div/div) }2、在子组件中指定 props 的类型为 React.FCUserType并使用 props 接收和渲染数据 // 子组件1 const Son1: React.FCUserType (props) {return (div classNameson1p用户信息/pp{JSON.stringify(props)}/p/div) }// 子组件2 const Son2: React.FCUserType (props) {return (div classNameson2p用户信息/pp{JSON.stringify(props)}/p/div) }修改完成后点击父组件中的 button 按钮修改用户名我们发现两个子组件中的数据同步发生了变化。 7. 在子组件中实现点击按钮 age 自增操作 1、扩充 ActionType 的类型如下 // 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string } | { type: INCREMENT; payload: number }2、在 reducer 中添加 INCREMENT 的 case 匹配 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, action)switch (action.type) {case UPDATE_NAME:return { ...prevState, name: action.payload }// 添加 INCREMENT 的 case 匹配case INCREMENT:return { ...prevState, age: prevState.age action.payload }default:return prevState} }3、在子组件 Son1 中添加 1 的 button 按钮并绑定点击事件处理函数 // 子组件1 const Son1: React.FCUserType (props) {const add () {}return (div classNameson1p用户信息/pp{JSON.stringify(props)}/pbutton onClick{add}1/button/div) }4、现在的问题是子组件 Son1 中无法调用到父组件的 dispatch 函数。 为了解决这个问题我们需要在 Father 父组件中通过 props 把父组件中的 dispatch 传递给子组件 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state, dispatch] useReducer(reducer, defaultState, initAction)const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 })}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefatherSon1 {...state} dispatch{dispatch} /Son2 {...state} //div/div) }5、在 Son1 子组件中扩充 React.FCUserType 的类型并从 props 中把 dispatch 和用户信息对象分离出来 // 子组件1 const Son1: React.FCUserType { dispatch: React.DispatchActionType } (props) {const { dispatch, ...user } propsconst add () dispatch({ type: INCREMENT, payload: 1 })return (div classNameson1p用户信息/pp{JSON.stringify(user)}/pbutton onClick{add}1/button/div) }8. 在子组件中实现点击按钮 age 自减操作 扩充 ActionType 的类型如下 // 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string } | { type: INCREMENT; payload: number } | { type: DECREMENT; payload: number }在 reducer 中添加 DECREMENT 的 case 匹配 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, action)switch (action.type) {case UPDATE_NAME:return { ...prevState, name: action.payload }case INCREMENT:return { ...prevState, age: prevState.age action.payload }// 添加 DECREMENT 的 case 匹配case DECREMENT:return { ...prevState, age: prevState.age - action.payload }default:return prevState} }在子组件 Son2 中添加 -5 的 button 按钮并绑定点击事件处理函数 // 子组件2 const Son2: React.FCUserType (props) {const sub () { }return (div classNameson2p用户信息/pp{JSON.stringify(props)}/pbutton onClick{sub}-5/button/div) }现在的问题是子组件 Son2 中无法调用到父组件的 dispatch 函数。为了解决这个问题我们需要在 Father 父组件中通过 props 把父组件中的 dispatch 传递给子组件 // 父组件 export const Father: React.FC () {// useReducer(fn, 初始数据, 对初始数据进行处理的fn)const [state, dispatch] useReducer(reducer, defaultState, initAction)const onChangeName () {dispatch({ type: UPDATE_NAME, payload: 刘龙彬 })}return (divbutton onClick{onChangeName}修改 name 的值/buttondiv classNamefatherSon1 {...state} dispatch{dispatch} /Son2 {...state} dispatch{dispatch} //div/div) }在 Son2 子组件中扩充 React.FC 的类型并从 props 中把 dispatch 和用户信息对象分离出来 // 子组件2 const Son2: React.FCUserType { dispatch: React.DispatchActionType } (props) {const { dispatch, ...user } propsconst sub () dispatch({ type: DECREMENT, payload: 5 })return (div classNameson2p用户信息/pp{JSON.stringify(user)}/pbutton onClick{sub}-5/button/div) }9. 在 GrandSon 组件中实现重置按钮 1、扩充 ActionType 的类型如下 // 定义 action 的类型 type ActionType { type: UPDATE_NAME; payload: string } | { type: INCREMENT; payload: number } | { type: DECREMENT; payload: number } | { type: RESET }2、在 reducer 中添加 RESET 的 case 匹配 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, action)switch (action.type) {case UPDATE_NAME:return { ...prevState, name: action.payload }case INCREMENT:return { ...prevState, age: prevState.age action.payload }case DECREMENT:return { ...prevState, age: prevState.age - action.payload }// 添加 RESET 的 case 匹配case RESET:return defaultStatedefault:return prevState} }3、在 GrandSon 组件中添加重置按钮并绑定点击事件处理函数 const GrandSon: React.FC{ dispatch: React.DispatchActionType } (props) {const reset () props.dispatch({ type: RESET })return (h3这是 GrandSon 组件/h3button onClick{reset}重置/button/) }10. 使用 Immer 编写更简洁的 reducer 更新逻辑 解决每次重新为 对象/数组 解除引用的问题 1、安装 immer 相关的依赖包 npm install immer use-immer -S2、从 use-immer 中导入 useImmerReducer 函数并替换掉 React 官方的 useReducer 函数的调用 // 1. 导入 useImmerReducer import { useImmerReducer } from use-immer// 父组件 export const Father: React.FC () {// 2. 把 useReducer() 的调用替换成 useImmerReducer()const [state, dispatch] useImmerReducer(reducer, defaultState, initAction) }3、修改 reducer 函数中的业务逻辑case 代码块中不再需要 return 不可变的新对象了只需要在 prevState 上进行修改即可。 Immer 内部会复制并返回新对象因此降低了用户的心智负担。改造后的 reducer 代码如下 const reducer (prevState: UserType, action: ActionType) {console.log(触发了 reducer 函数, action)switch (action.type) {case UPDATE_NAME:// return { ...prevState, name: action.payload }prevState.name action.payloadbreakcase INCREMENT:// return { ...prevState, age: prevState.age action.payload }prevState.age action.payloadbreakcase DECREMENT:// return { ...prevState, age: prevState.age - action.payload }prevState.age - action.payloadbreakcase RESET:return defaultStatedefault:return prevState} }
http://www.hkea.cn/news/14284266/

相关文章:

  • 高仿卡西欧手表网站制作大型网站开发
  • 营销网站建设方案网站收录查询api
  • dede网站建设步骤郑州seo培训
  • 华为荣耀官网网站外贸网站建设推广
  • 做企业品牌网站的公司qq头像网站源码
  • 苏州网站制作搭建网上销售渠道
  • 大连网站推广招聘找平面设计师网站
  • 讯美 深圳网站建设wordpress 本地化
  • 家里公网宽带做网站要备案么做网站还 淘宝
  • 深圳建设网站top028唐山哪里有做网站的
  • 邢台市做网站电话会网站建设如何找工作
  • 如何自己做网站挣钱牡丹江营商环境建设监督局网站
  • 怎么使用dw做一个网站上海做家庭影院的公司网站
  • 网站后台内容编辑器网站开发费用会计分录
  • 外贸网站推广哪个比较好东莞seo网站制作报价
  • 网站外链建设需要考核棋牌类网站开发
  • 做创意美食的视频网站营销成功的案例
  • 个人网站备案申请中国商业联盟官网
  • 怎么做网站 白江苏建设准考证打印在哪个网站
  • 用ps怎么做网站背景做网站页面的视频
  • 丹东网站开发国外网站dns 地址禁止
  • 重庆便宜做网站的东莞网站建设多长时间
  • 可以做c语言任务的网站农业电商网站建设
  • 网站建设与网页设计制作教程wordpress 查看更多
  • 营销型网站建设教学wordpress relocate
  • 国外做蛋糕的网站厦门seo排名扣费
  • 网站用途说明网页版微信登录入口文件传输
  • 可以做点赞的网站赚钱开发新闻类网站
  • 深圳建设网站seo 手机html网页设计作业成品代码
  • 国外app素材网站义乌网一件代发