亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React Context與setState詳解使用方法

 更新時(shí)間:2022年11月28日 17:05:21   作者:_聰明勇敢有力氣  
Context提供了一個(gè)無(wú)需為每層組件手動(dòng)添加props,就能在組件樹(shù)間進(jìn)行數(shù)據(jù)傳遞的方法。在一個(gè)典型的 React 應(yīng)用中,數(shù)據(jù)是通過(guò)props屬性自上而下(由父及子)進(jìn)行傳遞的,但這種做法對(duì)于某些類(lèi)型的屬性而言是極其繁瑣的

React中的插槽(slot)

React對(duì)于需要插槽的情況非常靈活,有兩種方案可以實(shí)現(xiàn):

組件的children子元素;

props屬性傳遞React元素

children實(shí)現(xiàn)插槽

每個(gè)組件都可以獲取到 props.children:它包含組件的開(kāi)始標(biāo)簽和結(jié)束標(biāo)簽之間的內(nèi)容。

App.jsx

import React, { Component } from 'react'
import NavBar from './nav-bar'
import NavBarTwo from './nav-bar-two'
export class App extends Component {
  render() {
    const btn = <button>按鈕2</button>
    return (
      <div>
        {/* 1.使用children實(shí)現(xiàn)插槽 */}
        <NavBar>
          <button>按鈕</button>
          <h2>哈哈哈</h2>
          <i>斜體文本</i>
        </NavBar>
      </div>
    )
  }
}
export default App

NavBar.jsx

import React, { Component } from 'react'
// import PropTypes from "prop-types"
import "./style.css"
export class NavBar extends Component {
  render() {
    const { children } = this.props
    console.log(children)
    return (
      <div className='nav-bar'>
        <div className="left">{children[0]}</div>
        <div className="center">{children[1]}</div>
        <div className="right">{children[2]}</div>
      </div>
    )
  }
}
// NavBar.propTypes = {
//   children: PropTypes.array
// }
export default NavBar

props實(shí)現(xiàn)插槽

app.jsx

import React, { Component } from 'react'
import NavBar from './nav-bar'
import NavBarTwo from './nav-bar-two'
export class App extends Component {
  render() {
    const btn = <button>按鈕2</button>
    return (
      <div>
        {/* 2.使用props實(shí)現(xiàn)插槽 */}
        <NavBarTwo 
          leftSlot={btn}
          centerSlot={<h2>呵呵呵</h2>}
          rightSlot={<i>斜體2</i>}
        />
      </div>
    )
  }
}
export default App

NavBarTwo.jsx

import React, { Component } from 'react'
export class NavBarTwo extends Component {
  render() {
    const { leftSlot, centerSlot, rightSlot } = this.props
    return (
      <div className='nav-bar'>
        <div className="left">{leftSlot}</div>
        <div className="center">{centerSlot}</div>
        <div className="right">{rightSlot}</div>
      </div>
    )
  }
}
export default NavBarTwo

Context應(yīng)用場(chǎng)景

非父子組件數(shù)據(jù)的共享:

在開(kāi)發(fā)中,比較常見(jiàn)的數(shù)據(jù)傳遞方式是通過(guò)props屬性自上而下(由父到子)進(jìn)行傳遞。

但是對(duì)于有一些場(chǎng)景:比如一些數(shù)據(jù)需要在多個(gè)組件中進(jìn)行共享(地區(qū)偏好、UI主題、用戶(hù)登錄狀態(tài)、用戶(hù)信息等)。

如果我們?cè)陧攲拥腁pp中定義這些信息,之后一層層傳遞下去,那么對(duì)于一些中間層不需要數(shù)據(jù)的組件來(lái)說(shuō),是一種冗余的操作。

但是,如果層級(jí)更多的話,一層層傳遞是非常麻煩,并且代碼是非常冗余的:

React提供了一個(gè)API:Context;

Context 提供了一種在組件之間共享此類(lèi)值的方式,而不必顯式地通過(guò)組件樹(shù)的逐層傳遞 props;

Context 設(shè)計(jì)目的是為了共享那些對(duì)于一個(gè)組件樹(shù)而言是“全局”的數(shù)據(jù),例如當(dāng)前認(rèn)證的用戶(hù)、主題或首選語(yǔ)言;

Context相關(guān)API

React.createContext

創(chuàng)建一個(gè)需要共享的Context對(duì)象:

如果一個(gè)組件訂閱了Context,那么這個(gè)組件會(huì)從離自身最近的那個(gè)匹配的 Provider 中讀取到當(dāng)前的context值;

defaultValue是組件在頂層查找過(guò)程中沒(méi)有找到對(duì)應(yīng)的Provider,那么就使用默認(rèn)值

theme-context.js

import React from "react"
// 1.創(chuàng)建一個(gè)Context
const ThemeContext = React.createContext({ color: "blue", size: 10 })
export default ThemeContext

user-context.js

import React from "react"
// 1.創(chuàng)建一個(gè)Context
const UserContext = React.createContext()
export default UserContext

Context.Provider

每個(gè) Context 對(duì)象都會(huì)返回一個(gè) Provider React 組件,它允許消費(fèi)組件訂閱 context 的變化:

Provider 接收一個(gè) value 屬性,傳遞給消費(fèi)組件;

一個(gè) Provider 可以和多個(gè)消費(fèi)組件有對(duì)應(yīng)關(guān)系;

多個(gè) Provider 也可以嵌套使用,里層的會(huì)覆蓋外層的數(shù)據(jù);

當(dāng) Provider 的 value 值發(fā)生變化時(shí),它內(nèi)部的所有消費(fèi)組件都會(huì)重新渲染;

import React, { Component } from 'react'
import Home from './Home'
import ThemeContext from "./context/theme-context"
import UserContext from './context/user-context'
import Profile from './Profile'
export class App extends Component {
  constructor() {
    super()
    this.state = {
      info: { name: "kobe", age: 30 }
    }
  }
  render() {
    const { info } = this.state
    return (
      <div>
        <h2>App</h2>
        {/* 1.給Home傳遞數(shù)據(jù) */}
        {/* <Home name="why" age={18}/>
        <Home name={info.name} age={info.age}/>
        <Home {...info}/> */}
        {/* 2.普通的Home */}
        {/* 第二步操作: 通過(guò)ThemeContext中Provider中value屬性為后代提供數(shù)據(jù) */}
        <UserContext.Provider value={{nickname: "kobe", age: 30}}>
          <ThemeContext.Provider value={{color: "red", size: "30"}}>
            <Home {...info}/>
          </ThemeContext.Provider>
        </UserContext.Provider>
        <Profile/>
      </div>
    )
  }
}
export default App

Class.contextType

掛載在 class 上的 contextType 屬性會(huì)被重賦值為一個(gè)由 React.createContext() 創(chuàng)建的 Context 對(duì)象:

這能讓你使用 this.context 來(lái)消費(fèi)最近 Context 上的那個(gè)值;

你可以在任何生命周期中訪問(wèn)到它,包括 render 函數(shù)中;

import React, { Component } from 'react'
import ThemeContext from './context/theme-context'
import UserContext from './context/user-context'
export class HomeInfo extends Component {
  render() {
    // 4.第四步操作: 獲取數(shù)據(jù), 并且使用數(shù)據(jù)
    console.log(this.context)
    return (
      <div>
        <h2>HomeInfo: {this.context.color}</h2>
        <UserContext.Consumer>
          {
            value => {
              return <h2>Info User: {value.nickname}</h2>
            }
          }
        </UserContext.Consumer>
      </div>
    )
  }
}
// 3.第三步操作: 設(shè)置組件的contextType為某一個(gè)Context
HomeInfo.contextType = ThemeContext
export default HomeInfo

Context.Consumer

這里,React 組件也可以訂閱到 context 變更。這能讓你在 函數(shù)式組件 中完成訂閱 context。

這里需要 函數(shù)作為子元素(function as child)這種做法;

這個(gè)函數(shù)接收當(dāng)前的 context 值,返回一個(gè) React 節(jié)點(diǎn);

什么時(shí)候使用Context.Consumer呢?

1.當(dāng)使用value的組件是一個(gè)函數(shù)式組件時(shí);

2.當(dāng)組件中需要使用多個(gè)Context時(shí);

import ThemeContext from "./context/theme-context"
function HomeBanner() {
  return <div>
    {/* 函數(shù)式組件中使用Context共享的數(shù)據(jù) */}
    <ThemeContext.Consumer>
      {
        value => {
          return <h2> Banner theme:{value.color}</h2>
        }
      }
    </ThemeContext.Consumer>
  </div>
}
export default HomeBanner

我們什么使用setState

開(kāi)發(fā)中我們并不能直接通過(guò)修改state的值來(lái)讓界面發(fā)生更新:

因?yàn)槲覀冃薷牧藄tate之后,希望React根據(jù)最新的State來(lái)重新渲染界面,但是這種方式的修改React并不知道數(shù)據(jù)發(fā)生了變化;

React并沒(méi)有實(shí)現(xiàn)類(lèi)似于Vue2中的Object.defineProperty或者Vue3中的Proxy的方式來(lái)監(jiān)聽(tīng)數(shù)據(jù)的變化;

我們必須通過(guò)setState來(lái)告知React數(shù)據(jù)已經(jīng)發(fā)生了變化;

疑惑:在組件中并沒(méi)有實(shí)現(xiàn)setState的方法,為什么可以調(diào)用呢?

原因很簡(jiǎn)單,setState方法是從Component中繼承過(guò)來(lái)的。

setState異步更新

setState的更新是異步的?

最終打印結(jié)果是Hello World;

可見(jiàn)setState是異步的操作,我們并不能在執(zhí)行完setState之后立馬拿到最新的state的結(jié)果

setState設(shè)計(jì)為異步,可以顯著的提升性能;

如果每次調(diào)用 setState都進(jìn)行一次更新,那么意味著render函數(shù)會(huì)被頻繁調(diào)用,界面重新渲染,這樣效率是很低的;

最好的辦法應(yīng)該是獲取到多個(gè)更新,之后進(jìn)行批量更新;

如果同步更新了state,但是還沒(méi)有執(zhí)行render函數(shù),那么state和props不能保持同步;

state和props不能保持一致性,會(huì)在開(kāi)發(fā)中產(chǎn)生很多的問(wèn)題;

如何獲取異步的結(jié)果

式一:setState的回調(diào)

setState接受兩個(gè)參數(shù):第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)會(huì)在更新后會(huì)執(zhí)行;

格式如下:setState(partialState, callback)

changeText() {
	this.setState({
		message: '你好'
	}), () => {
		console.log(this.state.message)
	}
}

當(dāng)然我們也可以在生命周期函數(shù)

componentDidUpdate(precProps, provState, snapshot) {
	console.log(this.state.message)
}

setState一定是異步的嗎(React18之前)

其實(shí)分成兩種情況:

在組件生命周期或React合成事件中,setState是異步;

在setTimeout或者原生dom事件中,setState是同步;

setState默認(rèn)是異步的 (React18之后)

在React18之后,默認(rèn)所有的操作都被放到了批處理中(異步處理)。

如果希望代碼可以同步會(huì)拿到,則需要執(zhí)行特殊的flushSync操作

import React, { Component } from 'react'
import { flushSync } from 'react-dom'
function Hello(props) {
  return <h2>{props.message}</h2>
}
export class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      message: "Hello World",
      counter: 0
    }
  }
  componentDidMount() {
    // 1.網(wǎng)絡(luò)請(qǐng)求一: banners
    // 2.網(wǎng)絡(luò)請(qǐng)求二: recommends
    // 3.網(wǎng)絡(luò)請(qǐng)求三: productlist
  }
  changeText() {
    setTimeout(() => {
      // 在react18之前, setTimeout中setState操作, 是同步操作
      // 在react18之后, setTimeout中setState異步操作(批處理)
      flushSync(() => {
        this.setState({ message: "你好啊, 李銀河" })
      })
      console.log(this.state.message)
    }, 0);
  }
  increment() {
  }
  render() {
    const { message, counter } = this.state
    console.log("render被執(zhí)行")
    return (
      <div>
        <h2>message: {message}</h2>
        <button onClick={e => this.changeText()}>修改文本</button>
        <h2>當(dāng)前計(jì)數(shù): {counter}</h2>
        <button onClick={e => this.increment()}>counter+1</button>

        <Hello message={message}/>
      </div>
    )
  }
}
export default App

到此這篇關(guān)于React Context與setState詳解使用方法的文章就介紹到這了,更多相關(guān)React Context與setState內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解React 父組件和子組件的數(shù)據(jù)傳輸

    詳解React 父組件和子組件的數(shù)據(jù)傳輸

    這篇文章主要介紹了React 父組件和子組件的數(shù)據(jù)傳輸?shù)南嚓P(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-04-04
  • React組件對(duì)子組件children進(jìn)行加強(qiáng)的方法

    React組件對(duì)子組件children進(jìn)行加強(qiáng)的方法

    這篇文章主要給大家介紹了關(guān)于React組件中對(duì)子組件children進(jìn)行加強(qiáng)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用React具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • react native帶索引的城市列表組件的實(shí)例代碼

    react native帶索引的城市列表組件的實(shí)例代碼

    本篇文章主要介紹了react-native城市列表組件的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • React+echarts?(echarts-for-react)?實(shí)現(xiàn)中國(guó)地圖及省份切換功能

    React+echarts?(echarts-for-react)?實(shí)現(xiàn)中國(guó)地圖及省份切換功能

    這篇文章主要介紹了React+echarts?(echarts-for-react)?畫(huà)中國(guó)地圖及省份切換,有足夠的地圖數(shù)據(jù),可以點(diǎn)擊到街道,示例我只出到市級(jí),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì)需要的朋友可以參考下
    2022-11-11
  • 詳解webpack + react + react-router 如何實(shí)現(xiàn)懶加載

    詳解webpack + react + react-router 如何實(shí)現(xiàn)懶加載

    這篇文章主要介紹了詳解webpack + react + react-router 如何實(shí)現(xiàn)懶加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-11-11
  • React實(shí)現(xiàn)一個(gè)拖拽排序組件的示例代碼

    React實(shí)現(xiàn)一個(gè)拖拽排序組件的示例代碼

    這篇文章主要給大家介紹了React實(shí)現(xiàn)一個(gè)拖拽排序組件?-?支持多行多列、支持TypeScript、支持Flip動(dòng)畫(huà)、可自定義拖拽區(qū)域,文章通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • React useMemo與useCallabck有什么區(qū)別

    React useMemo與useCallabck有什么區(qū)別

    useCallback和useMemo是一樣的東西,只是入?yún)⒂兴煌?,useCallback緩存的是回調(diào)函數(shù),如果依賴(lài)項(xiàng)沒(méi)有更新,就會(huì)使用緩存的回調(diào)函數(shù);useMemo緩存的是回調(diào)函數(shù)的return,如果依賴(lài)項(xiàng)沒(méi)有更新,就會(huì)使用緩存的return
    2022-12-12
  • react的context和props詳解

    react的context和props詳解

    這篇文章主要介紹了react的context和props的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下
    2021-11-11
  • react 原生實(shí)現(xiàn)頭像滾動(dòng)播放的示例

    react 原生實(shí)現(xiàn)頭像滾動(dòng)播放的示例

    這篇文章主要介紹了react 原生實(shí)現(xiàn)頭像滾動(dòng)播放的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Zustand介紹與使用 React狀態(tài)管理工具的解決方案

    Zustand介紹與使用 React狀態(tài)管理工具的解決方案

    本文主要介紹了Zustand,一種基于React的狀態(tài)管理庫(kù),Zustand以簡(jiǎn)潔易用、靈活性高及最小化原則等特點(diǎn)脫穎而出,旨在提供簡(jiǎn)單而強(qiáng)大的狀態(tài)管理功能
    2024-10-10

最新評(píng)論