学习react-Provider解决props需要层层传递问题

1.组件数据传递问题

数据传递:A(顶级组件)-》B组件(子组件)、C组件(孙子组件)…很多组件
这样得通过props层层传递到下面的组件
还有另一种解决方法,即通过全局对象来解决,使用Provider可以解决数据层层传递和每个组件都要传props的问题;

2.props传递例子

学习react-环境&手脚架&页面&路由
在上一节的路由配置文件中,HomePage传递了name值

// Router.tsx
const routes: RouteObject[] = [
    {
        path: '/',
        element:<HomePage name={"test"} /> //<Navigate to='home/one' /> // 重定向
    },
    {
        path: 'login',
        element: <LoginPage name={"login"} />
    },
    // 未匹配到页面
    {
        path: '*',
        element: <NotFoundPage name={"notfound"} />
    }
]

在这一节中,创建MainPage,并在HomePage中引用

// MainMeta.tsx
export interface MainProp extends MetaProp{
    
}

export interface MainState extends MetaState{
   
}
// MainPage.tsx
class MainPage extends Component<MainProp, MainState> {
    constructor(props: MainProp) {
        super(props);
        this.state = { count: 0 };
     }

    render() {
        const { name } = this.props; //解构赋值
      return <h1>Hello main page, {name}!</h1>;
    }
  }

MainPage在HomePage中引用,并用props继续给MainPage传递name值

// MainPage.tsx
class MainPage extends Component<MainProp, MainState> {
    constructor(props: MainProp) {
        super(props);
        this.state = { count: 0 };
     }

    render() {
        const { name } = this.props; //解构赋值
      return <h1>Hello main page, {name}!</h1>;
    }
  }

如下图props的name字段,值为test,一层层传递
props的name字段,值为test, 一层层传递

3.用全局对象context

1. state共同维护context(function模式)

首先创造Global.tsx和ConfigProvider.tsx

// Global.tsx
class Global {
    constructor() {
    }
    count = 0;
    name = 'react';
    loading = true;
}

const globalStore = new Global();
export {globalStore};
// ConfigProvider.tsx
export const configContext = React.createContext<
{ global: Global; setGlobal: React.Dispatch<React.SetStateAction<Global>>;} | null >(null);

export const useConfig= ()=>useContext(configContext)

interface Props{
    children: React.ReactNode
}
export function ConfigProvider({ children}:Props) {
    const [global, setGlobal] = useState(globalStore);
  
    return (
      <configContext.Provider value={{global, setGlobal}}>
          {children}
      </configContext.Provider>)
  }

在index.tsx引入ConfigProvider

// index.tsx
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <HashRouter>
      <ConfigProvider>
        <App />
      </ConfigProvider>
    </HashRouter>
    
  </React.StrictMode>
);

创建ActionBar.tsx,并获取Provider Global存储的值,并在点击事件里面触发改变Global存储的值

// ActionBar.tsx
const ActionBar = () => {

    const config = useConfig()

    return (
        <div onClick={() => {
            config?.setGlobal({...config.global, name:"kk"})
        }}>
            <h3>{config?.global.name}-test actionbar</h3>
        </div>
    );
}

export default ActionBar;

在MainPage.tsx里面引用ActionBar

// MainPage.tsx
class MainPage extends Component<MainProp, MainState> {
    constructor(props: MainProp) {
        super(props);
        this.state = { count: 0 };
     }

    render() {
        const { name } = this.props; //解构赋值
      return(
        <div>
          <ActionBar/>
          <h1>Hello main page, {name}! </h1>
        </div>
      
      ); 
    }
  }

2. state共同维护context(class 模式)

首先创建Global.tsx和ThemeProvider.tsx

// Global.tsx
export class Global {
    constructor() {
    }
    type = "";
    count = 0;
    name = 'react';
    loading = true;
}

const globalStore = new Global();
export {globalStore};
// ThemeProvider.tsx
export interface ThemeContextStore{
    global: Global; setGlobal: React.Dispatch<React.SetStateAction<Global>>;
}
export const ThemeContext = React.createContext< ThemeContextStore | null >(null);

interface Props{
    children: React.ReactNode
}
export function ThemeProvider({ children}:Props) {
    const [global, setGlobal] = useState(globalStore);
  
    return (
      <ThemeContext.Provider value={{global, setGlobal}}>
          {children}
      </ThemeContext.Provider>)
  }

在index.tsx引入ThemeProvider

// index.tsx
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <HashRouter>
      <ThemeProvider>
        <App />
      </ThemeProvider>
    </HashRouter>
    
  </React.StrictMode>
);

在MainPage.tsx里面用consumer使用 context

class MainPage extends Component<MainProp, MainState> {
  
    static contextType=ThemeContext
    constructor(props: MainProp) {
        super(props);
        this.state = { count: 0 };
     }

    render() {
      
        const { name } = this.props; //解构赋值
      return(
        <ThemeContext.Consumer>
          {
            (test)=>(
              <div onClick={()=>{ test?.setGlobal({...test?.global, name:"ok"})}}>
                  {name}={test?.global.name}
              </div>
            )
          }
        </ThemeContext.Consumer>
      
      ); 
    }
  }
  
  export default MainPage;  

3.使用reducer 维护context

首先创建Global.tsx和Provider.tsx

// Global.tsx
export class Global {
    constructor() {
    }
    type = "";
    count = 0;
    name = 'react';
    loading = true;
}

const globalStore = new Global();
export {globalStore};
// Provider.tsx
export const stores = {globalStore};
type Action = {
  type:'set'|'get',
  key:keyof Global,
  value:any
}

type GlobalContext = {
  global:Global
  dispatch:React.Dispatch<Action>
}

export const storesContext = React.createContext<GlobalContext | null>(null);

export const useGlobal = ():GlobalContext|null => React.useContext(storesContext);

interface Props{
  children: React.ReactNode
}

function globalReducer(global:Global, action:Action):Global {
  switch (action.type) {
    case 'get':{
      return global;
    }
    case 'set': {
      
      return {...global, [action.key]:action.value};
    }
    default: {
      throw Error('Unknown action: ' + action.type);
    }
  }
}

export function StoresProvider({ children}:Props) {
    const [global, dispatch] = useReducer(globalReducer, globalStore);
  
    return (
      <storesContext.Provider value={{global, dispatch}}>
          {children}
      </storesContext.Provider>
    );
  }

在index.tsx引入Provider

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <HashRouter>
      <StoresProvider>
        <App />
      </StoresProvider>
    </HashRouter>
    
  </React.StrictMode>
);

创建TitleBar.tsx,并获取Provider Global存储的值,并在点击事件里面触发改变Global存储的值

// TitleBar.tsx
onst TitleBar = () => {
    const [name, setName] = useState("do");
    const globalContext = useGlobal ();


    return (
        <div onClick={() => {
            globalContext?.dispatch({
                type: 'set',
                key: "count",
                value:1

              });
            //setName("click")
        }}>
            <h3>{globalContext?.global.count}- {name}</h3>
        </div>
    );
}

export default TitleBar;

在MainPage.tsx里面引入Titlebar

// MainPage.tsx
class MainPage extends Component<MainProp, MainState> {
    constructor(props: MainProp) {
        super(props);
        this.state = { count: 0 };
     }

    render() {
        const { name } = this.props; //解构赋值
      return(
        <div>
          <TitleBar/>
          <h1>Hello main page, {name}! </h1>
        </div>
      
      ); 
    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React hooks 可以通过两种方式传递参数: 1. 使用 useState hook useState hook 可以接收一个初始值参数,这个参数可以是任何类型的值,包括对象和数组。例如,以下代码展示了如何使用 useState hook 创建一个计数器: ``` import React, { useState } from 'react'; function Counter({ initialCount }) { const [count, setCount] = useState(initialCount); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } export default Counter; ``` 在这个例子中,我们使用 initialCount 参数来初始化计数器的值,然后将其传递给 useState hook。 2. 使用 useContext hook useContext hook 可以让我们在组件之间共享数据,从而避免 props 层层传递问题。例如,以下代码展示了如何使用 useContext hook 在组件之间共享数据: ``` import React, { useContext } from 'react'; const MyContext = React.createContext(); function ParentComponent({ someValue }) { return ( <MyContext.Provider value={someValue}> <ChildComponent /> </MyContext.Provider> ); } function ChildComponent() { const someValue = useContext(MyContext); return <p>Some value: {someValue}</p>; } export default ParentComponent; ``` 在这个例子中,我们创建了一个 MyContext 对象,并将其传递Provider 组件。然后,在 ChildComponent 组件中,我们使用 useContext hook 获取 MyContext 对象中的值。这个值可以是任何类型的数据,包括函数和对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值