programing

렌더링 기능 외부에서 React Context에 액세스

minecode 2021. 1. 15. 07:58
반응형

렌더링 기능 외부에서 React Context에 액세스


Redux 대신 새로운 React Context API를 사용하여 새로운 앱을 개발 Redux중입니다. 예를 들어 사용자 목록 을 가져와야 할 때를 사용하여 단순히 componentDidMount내 작업을 호출 했지만 이제는 React Context를 사용하여 내 작업이 내부에 있습니다. 내 렌더링 함수 안에있는 내 소비자, 즉 내 렌더링 함수가 호출 될 때마다 내 작업을 호출하여 내 사용자 목록을 가져 오며 불필요한 요청을 많이 할 것이기 때문에 좋지 않습니다.

그렇다면 componentDidMount렌더링을 호출하는 대신 in과 같이 내 작업을 한 번만 호출 할 수있는 방법은 무엇입니까?

예를 들어 다음 코드를 살펴보십시오.

다음 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는 내 사용자 뷰 소품에 살지 않기 때문에 작동 하지 않습니다. 이것이 가능하다면 올바른 방법은 무엇입니까?


편집 : 의 반응 - 후크의 도입으로 v16.8.0 , 당신은을 사용하여 기능적 구성 요소의 컨텍스트를 사용할 수있는 useContext후크를

const Users = () => {
    const contextValue = useContext(UserContext);
    // rest logic here
}

편집 : 버전 16.6.0 부터. 당신은 사용 수명주기 방법에 컨텍스트를 사용할 수있다 this.context처럼

class Users extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* perform a side-effect at mount using the value of UserContext */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* render something based on the value of UserContext */
  }
}
Users.contextType = UserContext; // This part is important to access context values

버전 16.6.0 이전에는 다음과 같은 방식으로 수행 할 수 있습니다.

라이프 사이클 방법에서 Context를 사용하려면 다음과 같이 구성 요소를 작성하십시오.

class Users extends React.Component {
  componentDidMount(){
    this.props.getUsers();
  }

  render(){
    const { users } = this.props;
    return(

            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
    )
  }
}
export default props => ( <UserContext.Consumer>
        {({users, getUsers}) => {
           return <Users {...props} users={users} getUsers={getUsers} />
        }}
      </UserContext.Consumer>
)

Generally you would maintain one context in your App and it makes sense to package the above login in an HOC so as to reuse it. You can write it like

import UserContext from 'path/to/UserContext';

const withUserContext = Component => {
  return props => {
    return (
      <UserContext.Consumer>
        {({users, getUsers}) => {
          return <Component {...props} users={users} getUsers={getUsers} />;
        }}
      </UserContext.Consumer>
    );
  };
};

and then you can use it like

export default withUserContext(User);

Ok, I found a way to do this with a limitation. With the with-context library I managed to insert all my consumer data into my component props.

But, to insert more than one consumer into the same component is complicated to do, you have to create mixed consumers with this library, which makes not elegant the code and non productive.

The link to this library: https://github.com/SunHuawei/with-context

EDIT: Actually you don't need to use the multi context api that with-context provide, in fact, you can use the simple api and make a decorator for each of your context and if you want to use more than one consumer in you component, just declare above your class as much decorators as you want!


For my part it was enough to add .bind(this) to the event. This is how my Component looks like.

// 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>
  }
}

maybe you call a component with lowercase like

<Context.consumer> 

this is wrong you must call with uppercase like

<Context.Consumer> 

You have to pass context in higher parent component to get access as a props in child.

ReferenceURL : https://stackoverflow.com/questions/49809884/access-react-context-outside-of-render-function

반응형