React.createContext
是 React 的上下文 API 的核心方法之一,提供了一种无需通过组件树逐层传递 props
的方式来共享数据。它特别适合于全局状态的管理,比如用户信息、主题设置等。下面我将详细介绍 React.createContext
的多种使用方法,并提供相应的代码示例。
1. 基础使用
- 目的:在父组件中定义一个
Context
,子组件可以直接通过useContext
来获取上下文中的数据。
示例:
import React, { createContext, useContext } from 'react';
// 创建一个 Context
const MyContext = createContext();
const GrandChild = () => {
const value = useContext(MyContext); // 使用 useContext 获取数据
return <div>{value}</div>;
};
const Child = () => <GrandChild />;
const Parent = () => {
const contextValue = "Hello from Context";
return (
<MyContext.Provider value={contextValue}>
<Child />
</MyContext.Provider>
);
};
export default Parent;
2. 使用 Context 传递对象
- 目的:在 Context 中传递一个复杂的数据结构,比如对象或数组。
示例:
import React, { createContext, useContext } from 'react';
// 创建一个 Context
const UserContext = createContext();
const UserProfile = () => {
const user = useContext(UserContext); // 使用 useContext 获取对象
return (
<div>
<p>Name: {user.name}</p>
<p>Age: {user.age}</p>
</div>
);
};
const Parent = () => {
const user = { name: "John Doe", age: 30 };
return (
<UserContext.Provider value={user}>
<UserProfile />
</UserContext.Provider>
);
};
export default Parent;
3. 使用 Context 与 useState
配合
- 目的:在 Context 中传递动态状态,可以在组件中修改 Context 中的数据。
示例:
import React, { createContext, useContext, useState } from 'react';
// 创建一个 Context
const CounterContext = createContext();
const CounterDisplay = () => {
const [count] = useContext(CounterContext); // 通过 useContext 获取 count
return <div>Count: {count}</div>;
};
const CounterControls = () => {
const [, setCount] = useContext(CounterContext); // 通过 useContext 获取 setCount
return (
<button onClick={() => setCount(prev => prev + 1)}>
Increment
</button>
);
};
const Parent = () => {
const counterState = useState(0); // 使用 useState 创建计数器状态
return (
<CounterContext.Provider value={counterState}>
<CounterDisplay />
<CounterControls />
</CounterContext.Provider>
);
};
export default Parent;
4. 多 Context 配合使用
- 目的:在一个组件中使用多个 Context,分别传递不同的状态或数据。
示例:
import React, { createContext, useContext } from 'react';
// 创建两个 Context
const ThemeContext = createContext();
const UserContext = createContext();
const Dashboard = () => {
const theme = useContext(ThemeContext);
const user = useContext(UserContext);
return (
<div style={{ background: theme.background, color: theme.color }}>
<p>Welcome, {user.name}</p>
</div>
);
};
const Parent = () => {
const theme = { background: "black", color: "white" };
const user = { name: "Jane Doe" };
return (
<ThemeContext.Provider value={theme}>
<UserContext.Provider value={user}>
<Dashboard />
</UserContext.Provider>
</ThemeContext.Provider>
);
};
export default Parent;
5. Context API 与 useReducer
结合
- 目的:在复杂状态管理中,通过
useReducer
管理状态,并将其与 Context 结合使用。
示例:
import React, { createContext, useContext, useReducer } from 'react';
// 创建一个 Context
const CounterContext = createContext();
// 定义 reducer 函数
const counterReducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
};
const CounterDisplay = () => {
const { state } = useContext(CounterContext); // 获取 state
return <div>Count: {state.count}</div>;
};
const CounterControls = () => {
const { dispatch } = useContext(CounterContext); // 获取 dispatch
return (
<>
<button onClick={() => dispatch({ type: 'increment' })}>
Increment
</button>
<button onClick={() => dispatch({ type: 'decrement' })}>
Decrement
</button>
</>
);
};
const Parent = () => {
const [state, dispatch] = useReducer(counterReducer, { count: 0 }); // 使用 useReducer
return (
<CounterContext.Provider value={{ state, dispatch }}>
<CounterDisplay />
<CounterControls />
</CounterContext.Provider>
);
};
export default Parent;
6. 全局 Context
- 目的:创建一个全局的 Context,通常用于应用级别的状态管理,比如用户认证信息。
示例:
import React, { createContext, useContext, useState } from 'react';
// 创建全局 Context
const AuthContext = createContext();
export const useAuth = () => {
return useContext(AuthContext); // 自定义 Hook 方便使用
};
const AuthProvider = ({ children }) => {
const [isAuthenticated, setAuthenticated] = useState(false);
const login = () => setAuthenticated(true);
const logout = () => setAuthenticated(false);
return (
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
};
const Dashboard = () => {
const { isAuthenticated, logout } = useAuth();
return (
<div>
{isAuthenticated ? (
<>
<p>Welcome, User!</p>
<button onClick={logout}>Logout</button>
</>
) : (
<p>Please log in.</p>
)}
</div>
);
};
const App = () => {
return (
<AuthProvider>
<Dashboard />
</AuthProvider>
);
};
export default App;
这些例子展示了 React.createContext
的多种使用方法,从简单的数据共享到复杂的状态管理,希望能帮助你更好地理解和应用 Context API
。
7.例子:
案例 1: createContext封装 A组件 ,在A组件里 请求接口结果 赋值 useState 的变量 value。 然后在B组件 使用 A组件 包裹 C组件 在 C组件 获取使用 A组件里的 变量value 的值
你可以通过封装 Context
来实现这个功能。在 A
组件中,我们会使用 useContext
和 useState
来管理状态,并通过调用接口将结果赋值给 useState
的变量 value
。然后在 B
组件中,将 C
组件包裹在 A
组件内,使得 C
组件能够通过 useContext
获取 value
的值。
以下是详细的实现步骤和代码示例:
1. 创建 A
组件并封装 Context
首先,在 A
组件中,我们会创建一个 Context
,然后使用 useState
来管理状态,并在 useEffect
中调用接口获取数据,将结果存储在 value
中。最后,我们通过 Context.Provider
将 value
传递给子组件。
import React, { createContext, useState, useEffect, useContext } from 'react';
// 创建 Context
const MyContext = createContext();
// 封装 A 组件
export const A = ({ children }) => {
const [value, setValue] = useState(null);
useEffect(() => {
// 模拟请求接口,获取数据
const fetchData = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
setValue(data);
};
fetchData();
}, []);
return (
<MyContext.Provider value={value}>
{children}
</MyContext.Provider>
);
};
// 创建自定义 Hook 方便获取 Context 值
export const useMyContext = () => {
return useContext(MyContext);
};
2. 在 B
组件中使用 A
组件包裹 C
组件
在 B
组件中,我们将 C
组件包裹在 A
组件内,使 C
组件能够访问 A
组件中的 value
值。
import React from 'react';
import { A } from './A'; // 引入 A 组件
import C from './C'; // 引入 C 组件
const B = () => {
return (
<A>
<C />
</A>
);
};
export default B;
3. 在 C
组件中获取 value
的值
在 C
组件中,我们通过 useMyContext
自定义 Hook 获取 A
组件中的 value
值,并将其展示在界面上。
import React from 'react';
import { useMyContext } from './A'; // 使用自定义 Hook 获取 Context 值
const C = () => {
const value = useMyContext();
return (
<div>
{value ? (
<div>
<h1>{value.title}</h1>
<p>{value.body}</p>
</div>
) : (
<p>Loading...</p>
)}
</div>
);
};
export default C;
4. 最终的结构
最终的组件层级结构是:
B
组件使用A
组件包裹C
组件。A
组件负责请求数据并通过Context
传递数据。C
组件通过useMyContext
获取A
组件中的value
值并展示。
5. 运行效果
当你运行这个示例时,C
组件会首先显示 Loading...
,在 A
组件成功请求接口并赋值 value
后,C
组件会显示接口返回的 title
和 body
信息。
这个实现方案清晰地展示了如何在 React 中使用 createContext
封装组件,并在子组件中获取并使用封装组件中的状态数据。
案例 2: createContext封装 A组件 ,在A组件里 请求接口结果 赋值 useState 的变量 value。 然后在B组件 获取使用 A组件里的 变量value 的值
要在 React
中实现 createContext
封装的 A
组件,并在 B
组件中获取并使用 A
组件中的 value
值,你可以按照以下步骤进行。
1. 创建 A
组件并封装 Context
首先,创建 A
组件,并在其中使用 useContext
和 useState
来管理状态。通过 useEffect
调用接口,将返回的数据存储在 value
中。然后通过 Context.Provider
将 value
传递给 B
组件。
import React, { createContext, useState, useEffect } from 'react';
// 创建 Context
const MyContext = createContext();
// 封装 A 组件
export const A = ({ children }) => {
const [value, setValue] = useState(null);
useEffect(() => {
// 模拟请求接口,获取数据
const fetchData = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
setValue(data);
};
fetchData();
}, []);
return (
<MyContext.Provider value={value}>
{children}
</MyContext.Provider>
);
};
// 创建自定义 Hook 方便获取 Context 值
export const useMyContext = () => {
return React.useContext(MyContext);
};
2. 在 B
组件中获取 value
的值
在 B
组件中,使用 A
组件包裹内容,并通过 useMyContext
自定义 Hook 获取 value
的值。
import React from 'react';
import { A, useMyContext } from './A'; // 引入 A 组件和自定义 Hook
const B = () => {
const value = useMyContext(); // 获取 A 组件中的 value
return (
<A>
<div>
{value ? (
<div>
<h1>{value.title}</h1>
<p>{value.body}</p>
</div>
) : (
<p>Loading...</p>
)}
</div>
</A>
);
};
export default B;
3. 代码解释
- A 组件:通过
createContext
创建了一个上下文MyContext
。在A
组件内部,使用useState
来定义value
,通过useEffect
调用接口将数据保存到value
中。最后,通过MyContext.Provider
将value
传递给子组件。 - useMyContext 自定义 Hook:这是一个简单的 Hook,方便在
B
组件中直接获取MyContext
的值。 - B 组件:在
B
组件中,通过useMyContext
获取A
组件中的value
值,然后展示出来。如果value
为空,则显示Loading...
。
4. 运行效果
当你运行这个示例时,B
组件会首先显示 Loading...
。一旦 A
组件完成数据请求并赋值 value
后,B
组件会显示接口返回的 title
和 body
信息。
这种方法通过 createContext
以及 Context.Provider
实现了在不同组件间的状态共享,并避免了繁琐的 props
传递,代码结构更加清晰且易于维护。