“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情”
1. 简介
之前几天学习了React的组件创建,状态创建,父子组件传值等操作,今天的话就学习一个新的hook(useContext),并使用它进行非父子组件传递数据的一个操作
1.代码学习
1. Context
- 在之前的操作中只学习了父子组件的数据传递,如果想要爷孙组件,那么只能一层层的传递下去,就显得非常冗余,而且一旦组件需要更多从来自顶层组件的 props,你还得在中间层级一个一个加上去,这将会变得非常麻烦。
- Context 设计目的是为了共享那些“全局”的数据,例如当前认证的用户、主题或首选语言。
- 这个Hook 和 Vue的 provide / inject 功能一样,使用 Provider在顶层组件中提供数据,使用useContext在底层组件中获取数据。
2. 代码学习
- 先创建几个需要共享数据的组件
- App下使用的Main组件
- Main下使用的Footer组件,Header组件,再来一个公用组件Title组件
- 组件现在就是子孙级的组件,嵌套使用和一个公用。
1. App组件 function App() { return ( <Main/> ) } 2. Main 组件 function Main() { return <div> <Header/> <hr/> <div> 这是Main的Content </div> <hr/> <Footer/> </div> }- Header 组件
export function Header() { return <div> 这是Header </div> }- Footer组件
export function Footer() { return <div> 这是footer </div> }- 创建Context 共享容器
import {createContext, useContext, useState} from 'react' interface ContextType { id: string name: string getUser?: Function } const context = createContext<ContextType>({} as any)- 在父组件中使用Provider提供数据
function App() { const [user, SetUser] = useState({ id: "1", name: "共享组件数据", getUser: () => { alert("获取用户") } }) return ( <context.Provider value={user}> <Main/> </context.Provider> ) }- 在子组件中使用数据
通过 **const cot = useContext(context)**接收数据, 因为是ts可以直接通过先前定义好的属性名直接点读出
function Main() { const cot = useContext(context) return <div> <Header/> <hr/> <div> 这是Main的Content <p>{cot.name}</p> <p>{cot.id}</p> </div> <hr/> <Footer/> </div> }- 接下来我们将在Header和Footer 中使用,会发现没有context对象,因为在当前文件中是直接使用定义好的context实例
- 在其他文件中想要使用的话我们可以把这个context对象拿出来
- 为context创建一个单独的文件
import {createContext} from 'react' export interface ContextType { id: string name: string } export const context = createContext<ContextType>({} as any)- 组件使用
import {context} from '../UserContext' import {useContext} from 'react' export function Footer() { const cot = useContext(context) return <div> 这是footer <p>{cot.id}</p> <p>{cot.name}</p> </div> }- APP.tsx 文件使用
import './App.css' import {Footer} from './component/Footer' import {Header} from './component/Header' import {context, ContextType} from './UserContext' import {useContext, useState} from 'react' function Main() { const cot = useContext(context) return <div> <Header/> <hr/> <div> 这是Main的Content <p>{cot.name}</p> <p>{cot.id}</p> </div> <hr/> <Footer/> </div> } function App() { const [user, SetUser] = useState<ContextType>({ id: "123", name: "共享组件数据" }) return ( <context.Provider value={user}> <Main/> </context.Provider> ) } export default App
- 如果需要修改数据,也可以直接吧SetUser传递过去
const [user, SetUser] = useState<ContextType>({ id: "123", name: "共享组件数据" }) return ( <context.Provider value={{user, SetUser}}> <Main/> </context.Provider> ) - 接收方也需要结构赋值来接受
import {context} from '../context/UserContext'
import {useContext} from 'react'
export function Footer() {
const {user, SetUser} = useContext(context)
return <div>
这是footer
<p>{user.id}</p>
<p>{user.name}</p>
<button onClick={() => {SetUser({id: "2", name: "footer用户"})}}>
通过Footer更改
</button>
</div>
}
3. 总结
- 学习了通过Context,进行跨组件传递数据。
- 也可以直接传递修改方法,进行数据修改,一处修改全局数据都会发生改变。