likes
comments
collection
share

🔥你不得不了解的React组件之间通信

作者站长头像
站长
· 阅读数 21

你不得不了解的React组件之间通信

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第4篇文章 点击查看文章详情 🚀🚀

前言

react组件之间通信,作为前端面试最最最频繁的考点之一,与其反反复复去看去背知识点,还不如自己写篇文章总结一下来的有趣~🎉🎉

基本概念

提到react组件之间通信,脑海中自然而然就要想到五种基本情况

  • 父组件向子组件通信
  • 子组件向父组件通信
  • 兄弟组件通信
  • 跨级组件通信

    即父组件向子组件的子组件通信,向更深层子组件通信。

  • 非嵌套关系的组件通信

    即没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。

父子组件通信

废话不多说,我们直接看下面的例子👇

效果图

🔥你不得不了解的React组件之间通信

实现过程

// App.jsx
import { useState } from 'react'
import Father  from './Father'

function App() {

  return (
    <div className="App">
      <Father/>
    </div>
  )
}

export default App
// Father.jsx
import React from 'react'
import { useState } from 'react'
import Child from './Child'

export default function Father() {
    const [state,setState] = useState('state')

    return (
        <div>
            <Child state={state} setState={setState}></Child>
        </div>
    )
}

// Child.jsx
import React from 'react'

export default function Child(props) {
  const { state,setState } = props
  const onButtonClick = () => {
    setState('后代知道了')
  }
  return (
    <div>
        { state }
        <button onClick={onButtonClick}>后代知道了</button>
    </div>
  )
}

  • 在父子组件通信中,我们需要了解:

    • 父组件负责请求和处理数据

    • 子组件没有自己的状态,主要负责展示数据,和调用父组件修改数据的方法

    • 数据的改变发生在父组件里,父组件数据改变后,子组件重新渲染

在这个例子中不仅体现了父组件向子组件通信,还体现了子组件向父组件的通信

  • 父组件向子组件通信

    父组件自身定义了state属性,通过props属性传递给了子组件,在子组件中,用props就可以获取到这个state值

  • 子组件向父组件的通信

    子组件通过父组件传递过来的setState方法,改变父组件中state的值,实现了在子组件中改变了父组件状态

兄弟组件之间通信

效果图

🔥你不得不了解的React组件之间通信

实现过程

// App.jsx
import { useState } from 'react'
import Channel from './Channel'

function App() {

  return (
    <div className="App">
      <Channel/>
    </div>
  )
}

export default App
// Channel.jsx
import React, { useState } from 'react'
import ComA from './ComA';
import ComB from './ComB';

export default function Channel() {
    // 父组件负责状态管理
    const [stateA, setStateA] = useState("A");
    const [stateB, setStateB] = useState("B");

    return (
        <div>
            <ComA stateA={stateA} setStateB={setStateB} setStateA={setStateA}/>
            <ComB stateB={stateB} setStateA={setStateA} setStateB={setStateB}/>
        </div>
    )
}

// ComA.jsx
import React from 'react'

export default function ComA(props) {
    const { stateA, setStateA, setStateB} = props
    const onButtonClick = () => {
        setStateB(stateA)
    }
    const onResetButtonClick = () => {
        setStateA("A")
    }
  return (
    <div>
      {stateA}
      <button onClick={onButtonClick}>把B变成A</button>
      <button onClick={onResetButtonClick}>还原A</button>
    </div>
  )
}

// ComB.jsx
import React from 'react'

export default function ComB(props) {
    const { stateB, setStateA, setStateB} = props
    const onButtonClick = () => {
        setStateA(stateB)
    }
    const onResetButtonClick = () => {
        setStateA("B")
    }
  return (
    <div>
      {stateB}
        <button onClick={onButtonClick}>把A变成B</button>
        <button onClick={onResetButtonClick}>还原B</button>
    </div>
  )
}

兄弟组件(ComA,ComB)间通信,通过父组件(Channel)作为桥梁,仍然用的是props

跨级组件通信

效果图

🔥你不得不了解的React组件之间通信

实现过程

// App.jsx
import { useState } from 'react'
import Ancestor from './Ancestor'

function App() {

  return (
    <div className="App">
      <Ancestor/>
    </div>
  )
}

export default App

// Little.jsx
import React, { createContext, useState } from 'react'
import Little from './Litter'

// 1.使用createContext创建并初始化
export const Context = createContext();

function Child() {
    return (
        <div>
            <Little />
        </div>
    )
}

export default function Ancestor() {
    const [state, setState] = useState("state")
    return (
    // 2.在Provider圈定的范围内,传入读操作和写操作对象,
    // 然后可以使用上下文
        <Context.Provider value={{state, setState}}>
            <div>
                <Child />
            </div>
        </Context.Provider>
    )
}

// Litter.jsx

import React, {useContext} from 'react'
import { Context } from './Ancestor'

export default function Litter() {

    // 3. 最后使用useContext接受上下文,因为传入的是对象,
    // 则接受的也应该是对象
    const { state, setState } = useContext(Context)
    const onButtonClick = () => {
        setState('后代知道了');
    }
    return (
        <div>
            {state}
            <button onClick={onButtonClick}> 后代知道了</button>
        </div>
    )
}

又回到我们之前的定义

跨级组件通信

即父组件向子组件的子组件通信,向更深层子组件通信。

向更深层子组件通信,我们很容易联想到用父子组件中props传值,但是当我们业务很多,第一层向第十层,第一百层通信,难道也傻乎乎的一直用props传下去?

🙅🙅🙅NO!

这个时候 Context 来发挥作用了!

Context提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法。Context设计目的是为了共享那些对于一个组件树而言是“全局”的数据。使用context,我们可以避免通过中间元素传递props

非嵌套关系的组件通信

这里就比较复杂了,需要使用到redux进行一个全局的状态管理。 或者使用 useContext + useReducer 进行redux代替。

对这个感兴趣的朋友可以去了解一下,这里就不展开说了,抱歉了~

小结

  • 父组件向子组件通信:

    父组件通过 props 向子组件传递需要的信息。父传子是在父组件中直接绑定一个正常的属性,这个属性就是指具体的值,在子组件中,用props就可以获取到这个值

  • 子组件向父组件通信

    props+回调函数的方式,使用公共组件进行状态提升。子传父是先在父组件上绑定属性设置为一个函数,当子组件需要给父组件传值的时候,则通过props调用该函数将参数传入到该函数当中,此时就可以在父组件中的函数中接收到该参数了,这个参数则为子组件传过来的值

  • 兄弟组件通信:

    可以找到这两个兄弟节点共同的父节点, 结合父子间通信方式进行通信。

  • 跨级组件通信

    即父组件向子组件的子组件通信,向更深层子组件通信。

    使用props,利用中间组件层层传递,但是如果父组件结构较深,那么中间每一层组件都要去传递props,增加了复杂度,并且这些props并不是中间组件自己需要的。

    使用contextcontext相当于一个大容器,我们可以把要通信的内容放在这个容器中,这样不管嵌套多深,都可以随意取用,对于跨越多层的全局数据可以使用context实现。

  • 非嵌套关系的组件通信

    即没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。

    可以通过redux等进行全局状态管理

最后

又小小地总结了一个特别基础的问题

不求别的,就希望面试的时候能够和面试官多扯上那么一分钟

或者就是不要总是看了忘,忘了看。

⭐⭐⭐

最后的最后 all in all

点赞 + 关注 + 收藏 = 学会了

转载自:https://juejin.cn/post/7145423740350758949
评论
请登录