【react】react18的学习(四)--复合组件通信

文章详细介绍了React中组件间通信的方式,包括props、ref以及如何使用上下文对象实现更深层次的通信。同时,文章讨论了状态管理的重要性,提到了Redux作为解决方案,并逐步解释了如何设置和使用Redux,包括创建reducer、store,以及如何在组件中利用react-redux进行连接。最后,文章还提及了其他状态管理库如redux-toolkit和mobx作为替代方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇:【react】react18的学习(三)–hooks组件

1、父子通信:props、ref

父传子:props

  • 传给子组件状态数据;
  • 特殊地,props.children:将元素内容传给子组件;所以不要手动给子组件设置属性,会被标签内容覆盖;
  • 通过给子组件ref,获取子组件数据;

子传父

  • 调用父组件传来的方法,修改父组件的状态或传值;

2、祖先通信:上下文对象,跟props属性无关

包括父子、及更深层嵌套,就是借助一个共同组件上下文
借助上下文对象:类似vue事件总线this.$busprovider+inject的结合,定义上下文对象,在祖先组件使用并传值,子孙组件使用;

1、创建指定上下文对象

// voteContext.js
import React from 'react'
const VoteContext = React.createContext()
export default VoteContext

2、类组件使用:祖先组件提供方式1种;子孙组件使用方式2种

  • 祖先组件中导入:1种
// 祖先组件中导入
import VoteContext from '@/contexts/voteContext'
// 祖先组件使用并提供公共数据
<VoteContext.Provider
  value={{
    supNum,
    oppNum,
    toSup: this.toSup,
    toOpp: this.toOpp,
  }}
>
  <div>
    <div>总人数:{sum}</div>
    <Main></Main>
    <Footer></Footer>
  </div>
</VoteContext.Provider>
  • 后代组件使用:2种
// 后代组件使用
import VoteContext from '@/contexts/voteContext'
// 使用方式1:绑定到静态属性,类似属性校验
static contextType = VoteContext
let { supNum, oppNum } = this.context
// 使用方式2:标签方式
<VoteContext.Consumer>
  {context => {
    let { } = context
    return ()
  }}
</VoteContext.Consumer>

3、hooks组件使用
与类组件一样,区别就是使用hooks函数组件语法;且后代组件也有两种方式:标签、useContext

  • 祖先组件中导入:1种
// 祖先组件中导入
import VoteContext from '@/contexts/voteContext'
// 祖先组件使用并提供公共数据
<VoteContext.Provider
  value={{
    supNum,
    oppNum,
    change,
  }}
>
  <div>
    <div>总数:{sum}</div>
    <Main></Main>
    <Footer></Footer>
  </div>
</VoteContext.Provider>
  • 后代组件使用:2种
// 后代组件使用
import VoteContext from '@/contexts/voteContext'
// 使用方式1:hooks函数
import React, { useContext } from 'react'
const { change } = useContext(VoteContext)
// 使用方式2:标签方式
<VoteContext.Consumer>
  {context => {
    let { } = context
    return ()
  }}
</VoteContext.Consumer>

3、任意组件通信:状态管理

一般使用props、状态管理,比较常用,上下文比较难维护;
状态管理库方案:纯reduxredux与react-reduxredux-toolkit与react-reduxmobx

方案一:纯redux

redux,不仅可以用于react,而在react中使用时,可以借助官方react-redux来简化使用操作;

  • 第一步:编写对应reducer,即公共状态与处理方法;类似vuex中modules
let initial = {
  supNum: 10,
  oppNum: 0,
}
export default function voteReducer(preState = initial, action) {
  let { type } = action
  switch (type) {
    case 'VOTE_SUP':
      preState.supNum++
      break
    case 'VOTE_OPP':
      preState.oppNum++
      break

    default:
      break
  }
  return preState
}

  • 第二步:创建公共容器store,存储公共数据+事件池;分别对应reducer里的state、action
import { createStore } from 'redux'
import voteReducer from './reducer/voteReducer'
const store = createStore(voteReducer)
export default store
  • 第三步:让组件能够使用store;借助上下文通信方式;getState():从仓库中获取公共状态;
import ThemeContext from './ThemeContext'
import store from './store'
root.render(
  <ConfigProvider locale={zhCN}>
    <ThemeContext.Provider value={{ store }}>
      <Vote></Vote>
    </ThemeContext.Provider>
  </ConfigProvider>
  // 严格模式,会渲染两次,对不安全函数会报红色警告也能执行
  // <React.StrictMode></React.StrictMode>
)
// hooks子组件获取
const { store } = useContext(ThemeContext)
const { supNum, oppNum } = store.getState()
  • 第四步:让组件能够操作storedispatch({})派发:执行仓库中的Reducer,对公共状态进行操作,redux内部初始化会执行一次用于首次初始化状态;
onClick={() => {
  store.dispatch({ type: 'VOTE_SUP' })
}}
  • 第五步:让组件能够更新storesubscribe(()=>{})订阅:订阅方法存放在事件池中,当仓库中公共状态被修改后,到方法池执行方法更新组件;
// 让组件更新:setState、useState
// 所以需要给store一个方法,store中状态更新会执行这个方法,这个方法触发组件更新
const [aa, setaa] = useState(0)
useEffect(() => {
  //该方法返回unsubscribe方法,不用传参,用于移除当前订阅
  store.subscribe(() => {
    setaa(pre => {
      return pre + 1
    })
  })
}, [])
redux 工程化开发(3步)

combineReducers:合并各个模块reducer;

第一步:各模块reducer统一管理;(类似vuex modules)

// store/reducers/index.js
// redux工程化管理
import { combineReducers } from 'redux'
import voteReducer from './voteReducer'
const reducer = combineReducers({
  vote: voteReducer,
})
export default reducer
// store/index.js
import { createStore } from 'redux'
import reducer from './reducers'
const store = createStore(reducer)
export default store
// 组件使用
const { store } = useContext(ThemeContext)
const { supNum, oppNum } = store.getState().vote

补充:按模块化,使用

不足1:派发时:每个模块的reducer都会被找一遍;且不同模块action.type可能会冲突;

不足2:订阅后:更改某个模块状态,事件池中所有模块订阅的方法还是会遍历执行,导致所有组件更新,性能不好;

第二步:派发行为标识TYPE的统一管理;针对第二步不足1;

将action的type,都用模块名前缀统一命名管理,避免重复;

// store/action-types.js
export const VOTE_SUP = 'VOTE_SUP'
export const VOTE_OPP = 'VOTE_OPP'

创建reducer、组件派发时都可以使用变量

import * as TYPES from '../action-types'
  switch (type) {
    case TYPES.VOTE_SUP:
      preState.supNum++
      break
-----
import { VOTE_OPP, VOTE_SUP } from '../../store/action-types'
store.dispatch({ type: VOTE_SUP })

第三步:组件派发操作做统一管理;

类似定义reducer,每个模块定义voteAction.js,内部定义方法,返回{trpe:‘’},并最终合并成一个action;

// store/actions/voteAction.js
import * as TYPES from '../action-types'
const voteAction = {
  sup() {
    return { type: TYPES.VOTE_SUP }
  },
}
export default voteAction
// store/actions/index.js
import voteAction from './voteAction'
const action ={
  vote: voteAction,
}
export default action
// 组件使用
import action from '../../store/actions'
onClick={() => {
  store.dispatch(action.vote.sup())
}}

方案二:redux&react-redux

基于react对redux进行封装,主要用于简化redux在组件中的使用,而不是公共状态的创建;

步骤:

  • 第一步:redux工程化方式创建store,且reducer中返回的state需要深拷贝,否则当作状态没变不更新组件;
  • 第二步:将store传递给子组件,使用 react-redux 提供的Provider标签;
  • 第三步:子组件通过connect()()将状态、dispatch操作绑定到props上,进行操作即可;
// 导入store
import { Provider } from 'react-redux'
import store from './store'
---
<ConfigProvider locale={zhCN}>
  <Provider store={store}>
    <Vote></Vote>
  </Provider>
</ConfigProvider>
// 子组件
import React from 'react'
import { connect } from 'react-redux'

const Main = props => {
  const { supNum, oppNum, sup } = props
  return (
    <div className="main">
      <div>支持人数:{supNum}</div>
      <div>反对人数:{oppNum}</div>
      <Button type="primary" onClick={sup}>
        支持
      </Button>
    </div>
  )
}

export default connect(state => state.vote,action.vote)(Main)
----
// 派发操作:相当于将
 sup() {
    return { type: TYPES.VOTE_SUP }
  },
  //转为
   sup(dispatch) {
    dispatch({ type: TYPES.VOTE_SUP })
  },

优点:

  • 不需要手动订阅;

  • 组件只在所使用状态更改时才更新;

方案三:redux-toolkit与react-redux

具体参见:【react】react18的学习(七)–redux-toolkit

方案四:mobx

mobx具体内容:【react】react18的学习(八)–mobx介绍

下一篇:【react】react18的学习(五)–样式私有化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值