Я разрабатываю новое приложение, используя новый React Context API вместо Redux, и раньше, Redux
когда мне нужно было, например, получить список пользователей, я просто вызываю componentDidMount
свое действие, но теперь с React Context мои действия живут внутри my Consumer, который находится внутри моей функции рендеринга, а это означает, что каждый раз, когда вызывается моя функция рендеринга, она будет вызывать мое действие для получения списка пользователей, а это нехорошо, потому что я буду выполнять множество ненужных запросов.
Итак, как я могу вызвать свое действие только один раз, например, componentDidMount
вместо вызова рендеринга?
Чтобы проиллюстрировать это, посмотрите на этот код:
Предположим, я оборачиваю все Providers
в один компонент, например:
import React from 'react';
import UserProvider from './UserProvider';
import PostProvider from './PostProvider';
export default class Provider extends React.Component {
render(){
return(
<UserProvider>
<PostProvider>
{this.props.children}
</PostProvider>
</UserProvider>
)
}
}
Затем я помещаю этот компонент Provider в оболочку всего моего приложения, например:
import React from 'react';
import Provider from './providers/Provider';
import { Router } from './Router';
export default class App extends React.Component {
render() {
const Component = Router();
return(
<Provider>
<Component />
</Provider>
)
}
}
Теперь, например, в представлении моих пользователей это будет примерно так:
import React from 'react';
import UserContext from '../contexts/UserContext';
export default class Users extends React.Component {
render(){
return(
<UserContext.Consumer>
{({getUsers, users}) => {
getUsers();
return(
<h1>Users</h1>
<ul>
{users.map(user) => (
<li>{user.name}</li>
)}
</ul>
)
}}
</UserContext.Consumer>
)
}
}
Я хочу вот что:
import React from 'react';
import UserContext from '../contexts/UserContext';
export default class Users extends React.Component {
componentDidMount(){
this.props.getUsers();
}
render(){
return(
<UserContext.Consumer>
{({users}) => {
getUsers();
return(
<h1>Users</h1>
<ul>
{users.map(user) => (
<li>{user.name}</li>
)}
</ul>
)
}}
</UserContext.Consumer>
)
}
}
Но, конечно же, приведенный выше пример не работает, потому что getUsers
он не находится в моих свойствах представления пользователей. Как правильно это сделать, если это вообще возможно?
источник
this.context
в одном компоненте с несколькими контекстами? Предположим, у меня есть компонент, которому нужен доступ к UserContext и PostContext, как с этим справиться? Что я вижу, так это создание контекста, смешивающего оба, но это единственное или лучшее решение для этого?Хорошо, я нашел способ сделать это с ограничением. С помощью
with-context
библиотеки мне удалось вставить все данные о своих потребителях в свойства компонентов.Но вставить более одного потребителя в один и тот же компонент сложно, вы должны создать смешанных потребителей с этой библиотекой, что делает код не элегантным и непродуктивным.
Ссылка на эту библиотеку: https://github.com/SunHuawei/with-context
РЕДАКТИРОВАТЬ: На самом деле вам не нужно использовать multi context api, который
with-context
предоставляет, на самом деле, вы можете использовать простой api и сделать декоратор для каждого вашего контекста, и если вы хотите использовать более одного потребителя в своем компоненте, просто объявите над своим классом столько декораторов, сколько захотите!источник
С моей стороны этого было достаточно, чтобы добавить
.bind(this)
к событию. Так выглядит мой Компонент.// Stores File class RootStore { //...States, etc } const myRootContext = React.createContext(new RootStore()) export default myRootContext; // In Component class MyComp extends Component { static contextType = myRootContext; doSomething() { console.log() } render() { return <button onClick={this.doSomething.bind(this)}></button> } }
источник
Вы должны передать контекст в более высокий родительский компонент, чтобы получить доступ в качестве реквизита в дочернем компоненте.
источник