[reactjs] 렌더링 기능 외부에서 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>
)

일반적으로 앱에서 하나의 컨텍스트를 유지하고 위의 로그인을 HOC로 패키징하여 재사용하는 것이 좋습니다. 다음과 같이 쓸 수 있습니다.

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>
    );
  };
};

그런 다음 다음과 같이 사용할 수 있습니다.

export default withUserContext(User);


답변

좋아, 나는 이것을 제한하는 방법을 찾았다. with-context라이브러리를 사용하여 모든 소비자 데이터를 구성 요소 소품에 삽입 할 수있었습니다.

그러나 동일한 구성 요소에 둘 이상의 소비자를 삽입하려면이 라이브러리를 사용하여 혼합 소비자를 만들어야하므로 코드가 우아하지 않고 비생산적입니다.

이 라이브러리에 대한 링크 : https://github.com/SunHuawei/with-context

편집 : 실제로 with-context제공 하는 다중 컨텍스트 API를 사용할 필요가 없습니다. 실제로 간단한 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>
  }
}


답변

자식의 소품으로 액세스하려면 상위 부모 구성 요소에 컨텍스트를 전달해야합니다.


답변