Прослушивание изменений переменной ReactContext в потребительском компоненте - PullRequest
0 голосов
/ 07 мая 2019

Я использую ReactContext в своем проекте, и здесь у меня есть «потребительский» компонент, использующий некоторые контекстные переменные.Все работает нормально, за исключением случаев, когда я пытаюсь «прослушать» изменения в переменной «myName».

<MyContext.Consumer>
      {context => {
        return (
          <div>Hello, {context.myName}, your title is age {...}</div>
        )
      }}
</MyContext.Consumer>

Всякий раз, когда меняется переменная «myName», я хотел бы сделать вызов ajax, получить некоторые данные (например, age)) и отобразить его в компоненте.Я искал способ прослушать изменения для «myName», что лучше для этого?Я заметил, что хотя компонент отражает наиболее обновленное «myName», ни один из методов жизненного цикла React не вызывается при изменении myName.

Ответы [ 2 ]

0 голосов
/ 07 мая 2019

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

Воткороткий пример с использованием React-хуков -implementation CodeSandbox -example .

Основные моменты этого примера,

// Initialize context
const context = React.createContext({ name: "" });

/**
 * My provider component which has it's own state
 * for updating existing context.
 */
const MyProvider = ({ children }) => {
  const [state, setState] = React.useState({ name: "" });
  return (
    <context.Provider value={state}>
      <input
        value={state.name}
        onChange={({ target }) => {
          console.log(target.value);
          setState({ name: target.value });
        }}
      />
      {children}
    </context.Provider>
  );
};



/**
 * Context to consume existing parent component context
 */
const MyConsumer = ({ children }) => {
  return <context.Consumer>{ctx => <MyComponent {...ctx} />}</context.Consumer>;
};

/**
 * provide values as props to your component with lifecycle-methods.
 */
const MyComponent = ({ name }) => {
  const [fetchResult, setResult] = React.useState({});
  React.useEffect(() => {
    console.log("child updated with name: ", name);
    /**
     * Fetch some data and set it to local state
     */
    const mockFetchResult = {
      title: name + `\n${Math.random() * 1024}` // Dummy example to get some random data
    };
    setResult(mockFetchResult);
  }, [name]);
  return <p>{fetchResult.title}</p>;
};
0 голосов
/ 07 мая 2019

Вам необходимо добавить свойство contextType в свой класс ( docs ). Затем вы можете получить доступ к обновленному контексту в методах жизненного цикла. Я изменил пример из документации, чтобы показать это. Смотрите компонент ThemedButton. Вы можете закомментировать static contextType и заметить, что компонент не получает контекст.

const ThemeContext = React.createContext("light");

class App extends React.Component {
  state = {
    theme: "dark"
  };

  render() {
    // Use a Provider to pass the current theme to the tree below.
    // Any component can read it, no matter how deep it is.
    // In this example, we're passing "dark" as the current value.
    return (
      <ThemeContext.Provider value={this.state.theme}>
        <button
          onClick={() => {
            this.state.theme === "dark"
              ? this.setState({ theme: "light" })
              : this.setState({ theme: "dark" });
          }}
        >
          Change theme
        </button>
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // Assign a contextType to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  static contextType = ThemeContext;

  componentDidUpdate() {
    console.log("Update", this.context);
  }

  render() {
    return <div>{JSON.stringify(this.context)}</div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Если у вас нет синтаксиса открытых полей класса, вы можете использовать аналогичную версию ThemedButton.contextType = ThemeContext.

...