欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 学习react-Provider解决props需要层层传递问题

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

2025/3/17 22:31:47 来源:https://blog.csdn.net/jacklam200/article/details/140534994  浏览:    关键词:学习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=ThemeContextconstructor(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:Globaldispatch: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>); }

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词