日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

React?數據共享useContext的實現_React

作者:www當下 ? 更新時間: 2022-06-22 編程語言

因為疫情, 最近接手一個新項目。是React的。上次寫React已經過去1年多了。

雖然撿起來也不是什么難事,不過技術這個東西,長時間不用就容易忘記。

為了保證這個項目根其他平行項目的技術棧統一。

采用的是 Nextjs 、styled-components、useContext 、react-query、ts

今天不做重點介紹項目,還是說說在項目中碰到的問題。

這個足足折騰了差不多2個小時,我一直在排查其問題。

最后這個問題也是比較的詭異。

ReferenceError: Cannot access 'Context' before initialization This error happened while generating the page. Any console logs will be displayed in the terminal window.

引用錯誤 , 不能在初始化之前訪問Context , 在生成頁面的時候就已經發生。在Shell控制臺也有顯示輸出。

我嘗試過很多的辦法, 例如:換用引用的方式、多個Provider的位置調整,甚至只保留一個 , 依然無法解決。

后來我試試可能組建聲明的類型問題。

我平時對于寫組建的方式比較隨意。

最喜歡的一種方式就是

import { useState  , createContext} from 'react'
import Me from './me'
export const MyContext =  createContext({});
export default function Demo(){
  const [say , setSay] = useState('');
  return (
    <MyContext.Provider value={{say , setSay}}>
      <div>father</div>誰在講話 {say}
      <Me />
    </FatherContext.Provider>
  )
}

React.FC是函數式組件寫法,是在TypeScript使用的一個泛型,FC就是FunctionComponent的縮寫,事實上React.FC可以寫成React.FunctionComponent ( 我對這種寫法感覺太過于冗余 )

import React, { createContext, FunctionComponent, useState } from 'react'
import Me from './me'
interface DemoProps {
  say: string;
  setSay: React.Dispatch<React.SetStateAction<boolean>>;
  demoString?:string;
}
const defaultDemoProps: DemoProps = {
	isDay: true,
	setIsDay: (day) => day
};
export const MyContext = createContext<DemoProps>({...defaultDemoProps});
const Demo: React.FC<DemoProps> = ({ children, ...props }) => {
  const { say : propIsSay } = props;
  const [ isSay, setSay ] = useState(propIsDay)
  return <MyContext.Provider value={{ say,setSay}}>
      <Me />
    </MyContext.Provider>
}
export default Demo;

還有很多習慣使用class components

import React, { createContext, PureComponent } from 'react'
import Me from './me'
export const MyContext = createContext({})
export default class Demo extends PureComponent {
  state = {
    say:true, 
  }
  setSay ()=>{
    let say = !this.state.say
    this.setState({
      say
    });
  }
  render() {
    return(
      <MyContext.Provider value={{ say,setSay}}>
      <Me />
      <MyContext.Provider>
    )
  }
}

這是三種的構造方式

createContext 函數返回的有3個屬性分別是 Provider ( 提供者 )、Customer( 消費者 )、displayName ( 貌似用不到 )

import React, { Context, PureComponent } from 'react';
import {MyContext} from '../components/data';
import Memo from '../components/classDemo';
export const MyContext = React.createContext()
export default class CurstomerDemo extends PureComponent {
  static contextType = MyContext  // 重點是這句 用來指定
	constructor(props) {
		super(props);
	}
  handleClick = () => {
    console.log (this.context) // 獲取上下文 Provider 屬性
  }
	render() {
		return (
      <div>
        <button>Provider</button>
        <button onClick={this.handleClick}>Customer</button>
      </div>
		)
	}
}



import React, { useState  ,useContext, createContext} from 'react'
import {MyContext} from './Demo'
function useCountContext(CounterContext) {
  const context = useContext(MyContext) //重點這句話,用來獲取指定的上線文Context
  if (!context) {
    throw new Error('useCountContext must used within Context.Provider')
  }
  return context
}
export default function Me(props){
  let context = useCountContext(MyContext)
  let {say , setSay} = context
  return (
    <div>
      me
      <button onClick={()=>{
        setSay(say + ',同志們好')
      }}>come from grandpa Provier {say}</button>
    </div>
  )
}

其實關鍵的還是用函數方式來接受函數的Provider , 類組件來接受類組件的Provider。保證構造的一致。

PS:useContext 我個人覺得對于小型項目還是非常的不錯,但是對于復雜的數據,他的分層意識還是不夠清晰。thunk、saga、mobx 都在一定程度上在分層上更適合context。當然你也可以對context更進一步封裝。適合自己的才是最好!

原文鏈接:https://juejin.cn/post/7089380341437169694

欄目分類
最近更新