react中的三种方式实现祖孙数据共享

最近在学习react的hook,看完useContext后总结一下react中的三种实现祖孙数据共享的方式。
这是一个主题换肤的例子,分别用下面三种方式来实现。先上效果图:

在这里插入图片描述
下面是app.js中的代码:

import React from 'react';
import './App.css'

import PropsContext from './pages/props-context'
import ClassContext from './pages/class-context'
import UseContext from './pages/hook-context'

function App() {
  return (
    <div className="App">
      {/* 使用props实现数据共享 */}
      <PropsContext ></PropsContext >
      <hr/>
      {/* 使用class context实现数据共享 */}
      <ClassContext></ClassContext>
      <hr />
      {/* 使用userContext hook实现数据共享 */}
      <UseContext></UseContext>
    </div>
  );
}

export default App;

1. props-context

顾名思义使用props的方式将祖先组件的数据一层层传递给子组件。和vue一样,父组件通过自定义属性的方式将数据作为props传给子组件,不同的是react中可以传递一个HTML结构(实质上是可以通过JSX转换的js对象),render-props正是利用了这一点灵活渲染DOM实现自定义HTML结构。

import React, { Component } from 'react'
import './index.css'

const COLOR = ['#B5E61D', '#ED1C24', '#00A2E8', '#A349A4', '#B97A57', '#A349A4']

export default class grandfather extends Component {
  state = {
    theme: COLOR[0]
  }
  changeColor = () => {
    this.setState({
      theme: COLOR[Math.ceil(Math.random() * (COLOR.length - 1))]  // 随机获取颜色
    })
  }
  render() {
    return (
      <div className="grandfather">
        <div>当前主题为:{this.state.theme}</div>
        <div style={{ color: this.state.theme }}>grandfather</div>
        <Father theme={this.state.theme}></Father>
        <button className="fixed1" onClick={this.changeColor}>换肤</button>
      </div>
    )
  }
}

function Father(props) {
  return (
    <div className="father">
      <div style={{ color: props.theme }}>father</div>
      <Son theme={props.theme}></Son>
    </div>
  )
}

function Son(props) {
  return (
    <div className="son">
      <div style={{ color: props.theme }}>son</div>
    </div>
  )
}

2. class-context

在class类组件中使用context来将数据共享给子组件,不同于props-context,这种方式可以跨越N个父组件直接将数据传给子组件,并不需要父->子、父->子。。。链式传递。VUE中也有使用context来实现祖孙数据共享的方案,只不过人家叫provide-inject,而react中叫provide-consumer。

import React, { Component, createContext } from 'react'
import './index.css'

const COLOR = ['#B5E61D', '#ED1C24', '#00A2E8', '#A349A4', '#B97A57', '#A349A4']
const Theme = createContext(COLOR[1])

export default class grandfather extends Component {
  state = {
    theme: COLOR[0]
  }
  changeColor = () => {
    this.setState({
      theme: COLOR[Math.ceil(Math.random() * (COLOR.length - 1))]  // 随机获取颜色
    })
  }
  render() {
    return (
        <div className="grandfather">
          <div>当前主题为:{this.state.theme}</div>
          <div style={{ color: this.state.theme }}>grandfather</div>
          <Theme.Provider value={this.state.theme}>
            <Father></Father>
          </Theme.Provider >
          <button className="fixed2" onClick={this.changeColor}>换肤</button>
        </div>
      
    )
  }
}

function Father(props) {
  return (
    <div className="father">
      <Theme.Consumer>
        {
          (theme) => {
            return <div style={{ color: theme }}>father</div>
          }
        }
      </Theme.Consumer>
      <Son></Son>
    </div>
  )
}

function Son(props) {
  return (
    <div className="son">
      <Theme.Consumer>
        {
          (theme) => {
            return <div style={{ color: theme }}>son</div>
          }
        }
      </Theme.Consumer>
    </div>
  )
}

3. hook-context

hook中提供了useContext这个钩子配合createContext去实现爷孙数据共享。相当于是provide-useComtext模式。在hook中数据通过useState钩子存放,实参为初识值,返回值为存放的数据以及相应的改变这个数据的函数。

import React, { useState ,useContext, createContext } from 'react'
import './index.css'

const COLOR = ['#B5E61D', '#ED1C24', '#00A2E8', '#A349A4', '#B97A57', '#A349A4']
const Theme = createContext('#B5E61D')

export default function Grandfather() {
  const [ theme, setTheme ] = useState(COLOR[0])
  function changeColor() {
    setTheme(COLOR[Math.ceil(Math.random() * (COLOR.length - 1))])
  }
  return (
    <div className="grandfather">
      <div>当前主题为:{theme}</div>
      <div style={{ color: theme }}>grandfather</div>
      <Theme.Provider value={theme}>
        <Father></Father>
      </Theme.Provider>
      <button className="fixed3" onClick={changeColor}>换肤</button>
    </div>
  )
}
function Father(props) {
  return (
    <div className="father">
    // 在函数组件中一样可以使用Context.Consumer语法来拿数据
      <Theme.Consumer>
        {
          (theme) => <div style={{ color: theme }}>father</div>
        }
      </Theme.Consumer>
      <Son></Son>
    </div>
  )
}

function Son(props) {
  const theme = useContext(Theme) // 注意此处的Theme是开头createContext('#B5E61D')的返回值Theme
  return (
    <div className="son">
      <div style={{ color: theme }}>son</div>
    </div>
  )
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React是一种用于构建用户界面的JavaScript库,它将应用程序拆分成小而可重用的组件。而Hooks是React 16.8版本新增的特性,它可以让你在不编写 class 的情况下使用 state 以及其他 React 特性。 在React数据共享可以通过Context来实现。而封装Hooks组件可以通过自定义Hooks来实现。 下面是一个简单的例子,展示如何封装Hooks组件实现数据共享: ```javascript import React, { createContext, useContext, useState } from 'react'; // 创建一个Context对象 const CounterContext = createContext(); // 自定义Hook,提供计数器状态和操作函数 function useCounter() { const [count, setCount] = useState(0); const increment = () => { setCount(count + 1); }; const decrement = () => { setCount(count - 1); }; return [count, increment, decrement]; } // CounterProvider组件,提供计数器状态和操作函数 function CounterProvider(props) { const counter = useCounter(); return ( <CounterContext.Provider value={counter}> {props.children} </CounterContext.Provider> ); } // Counter组件,使用计数器状态和操作函数 function Counter() { const [count, increment, decrement] = useContext(CounterContext); return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); } // 在App组件使用CounterProvider和Counter组件 function App() { return ( <CounterProvider> <Counter /> </CounterProvider> ); } export default App; ``` 上面的例子,我们首先定义了一个自定义Hook useCounter,用于提供计数器状态和操作函数。然后,我们创建了一个CounterContext对象,并使用CounterProvider组件来提供计数器状态和操作函数。最后,我们使用useContext Hook在Counter组件获取计数器状态和操作函数,并渲染出来。 相关问题: 1. React的Context是什么? 2. Hooks是什么?有哪些常用的Hooks? 3. 自定义Hooks有什么好处? 4. 在React如何实现数据共享
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值