Перейти к основному содержимому

React: Контекст и хук useContext

В React существует проблема передачи свойств целевым компонентам. Обычно мы поднимаем данные по дереву компонентов, чтобы хранить их в одном месте. Но затем их приходится спускать вниз по цепочке пропсов для вывода на страницу. Иногда несколько уровней компонентов просто передают вниз ненужные им данные. чтобы они достигли цели.

function App() {
// храним данные пользователя в App
// но выводим в Header
const [user] = React.useState({ name: "Fred" });

return (
{/* Первый уровень передачи данных через незаинтересованный компонент Main */}
<Main user={user} />
);
}

const Main = ({ user }) => (
<>
{/* Второй уровень передачи данных */}
<Header user={user} />
<div>Main app content...</div>
</>
);

const Header = ({ user }) => <header>Welcome, {user.name}!</header>;

Чтобы избежать этого, можно воспользоваться React-концепцией контекста. Это общая область видимости для целого дерева компонентов.

// Создаем контекст для данных юзера
const UserContext = React.createContext();

function App() {
// Создаем состояние для хранения данных юзера
const [user] = React.useState({ name: "Fred" });

return (
{/* Оборачиваем родительский компонент в провайдер контекста */}
{/* Теперь данные юзера доступны всем дочерним компонентам */}
<UserContext.Provider value={user}>
<Main />
</UserContext.Provider>
);
}

const Main = () => (
<>
<Header />
<div>Main app content...</div>
</>
);

// Вместо пропсов используем UserContext.Consumer
const Header = () => (
<UserContext.Consumer>
{user => <header>Welcome, {user.name}!</header>}
</UserContext.Consumer>
);

С хуком useContext все становится еще проще:

const Header = () => {
// Помещаем контекст в переменную user
const user = React.useContext(UserContext);
// Избавляемся от обертки UserContext.Consumer
return <header>Welcome, {user.name}!</header>;
};