Opracowuję nową aplikację, używając nowego interfejsu API React Context zamiast Redux, a wcześniej, Redux
gdy potrzebowałem na przykład listy użytkowników, po prostu wzywam componentDidMount
swoją akcję, ale teraz, dzięki React Context, moje działania są wewnątrz mój Konsument, który znajduje się wewnątrz mojej funkcji renderującej, co oznacza, że za każdym razem, gdy moja funkcja renderująca jest wywoływana, wywoła moją akcję, aby uzyskać listę moich użytkowników, a to nie jest dobre, ponieważ będę wykonywać wiele niepotrzebnych żądań.
Jak więc mogę wywołać moją akcję tylko raz, na przykład in componentDidMount
zamiast wywoływania renderowania?
Aby to zilustrować, spójrz na ten kod:
Załóżmy, że zawijam wszystko Providers
w jeden komponent, w ten sposób:
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>
)
}
}
Następnie umieszczam ten komponent dostawcy opakowujący całą moją aplikację, w ten sposób:
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>
)
}
}
Teraz, na przykład, dla moich użytkowników, będzie to mniej więcej tak:
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>
)
}
}
Chcę tego:
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>
)
}
}
Ale oczywiście powyższy przykład nie działa, ponieważ getUsers
rekwizyty nie znajdują się w widoku moich użytkowników. Jaki jest właściwy sposób, aby to zrobić, jeśli jest to w ogóle możliwe?
źródło
this.context
wielu kontekstach w tym samym komponencie? Załóżmy, że mam komponent, który musi mieć dostęp do UserContext i PostContext, jak sobie z tym poradzić? To, co widzę, to stworzenie kontekstu łączącego oba, ale to jedyne lub lepsze rozwiązanie na to?Ok, znalazłem sposób na to z pewnymi ograniczeniami. Dzięki
with-context
bibliotece udało mi się wstawić wszystkie moje dane konsumenckie do moich elementów składowych.Ale wstawienie więcej niż jednego konsumenta do tego samego komponentu jest skomplikowane, musisz stworzyć mieszanych konsumentów za pomocą tej biblioteki, co sprawia, że kod jest nieelegancki i nieproduktywny.
Link do tej biblioteki: https://github.com/SunHuawei/with-context
EDYCJA: Właściwie nie musisz używać wielokontekstowego interfejsu API, który
with-context
zapewnia, w rzeczywistości, możesz użyć prostego interfejsu API i utworzyć dekorator dla każdego kontekstu, a jeśli chcesz użyć więcej niż jednego konsumenta w swoim komponencie, po prostu zadeklaruj ponad swoją klasę tylu dekoratorów, ile chcesz!źródło
Z mojej strony wystarczyło dodać
.bind(this)
do wydarzenia. Tak wygląda mój komponent.// 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> } }
źródło
Musisz przekazać kontekst w wyższym komponencie nadrzędnym, aby uzyskać dostęp jako rekwizyty w potomku.
źródło