因为疫情, 最近接手一个新项目。是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
更进一步封装。适合自己的才是最好!
到此这篇关于React 数据共享useContext的实现的文章就介绍到这了,更多相关React 数据共享useContext内容请搜索软件开发网以前的文章或继续浏览下面的相关文章希望大家以后多多支持软件开发网!