当上下文发生变化时,不应该自动更新使用上下文的子组件吗?

时间:2017-03-27 14:13:40

标签: javascript reactjs redux react-redux

我正在尝试创建本地化解决方案。

我有以下结构用于测试目的

index.js

import { Provider } from 'react-redux';
import store from './store';  //This is a redux store
import LocalizedComponent from './components/containers/HomeContainer';

function App() {
  return (
    <Provider store={store}>
      <LocalizedComponent />
    </Provider>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));

HomeContainer组件是一个HOC,它将简单的表示组件包装到本地化组件中。

localization.jsx

import React, { PropTypes } from 'react';
import STRINGS from 'strings'; //This is an object containing translations


const translate = mapper => (Component) => {
  function LocalizedComponent(props, { store }) {
    const language = store.getState().language;
    const translatedProps = mapper(STRINGS, language);
    return (
      <Component {...props} {...translatedProps} />
    );
  }
  LocalizedComponent.contextTypes = {
    store: React.PropTypes.object
  };

  return LocalizedComponent;
};

export default translate;

mapper是一个像

这样的函数
const mapTranslationToProps = (strings, language) => ({
  <property key>: strings.<some key>[language]
});

Component可能是这样的

Home.jsx

import React from 'react';

function SomeComponent(props) {
  return (
    <div>
      <p>{props.<property key>}</p>
    </div>
  );
}
SomeComponent.propTypes = {
  <property key>: React.PropTypes.string
};
SomeComponent.defaultProps = {
  <property key>: ''
};

export default SomeComponent;

为了将所有这些结合起来,我们这样做

HomeContainer.jsx

import Home from 'components/presentational/Home';
import translate from 'components/HOC/Localization';

const mapTranslationToProps = (strings, language) => ({
  <property key>: strings.<some key>[language]
});

LocalizedComponent = translate(mapTranslationToProps)(SomeComponent);

export default LocalizedComponent;

第一次渲染时,通过language从状态中选择正确的context,并相应地显示文本

但是,当我发送一个更改状态language的操作时,组件不会更新。

我的印象是,在适用的情况下,对上下文的更改会触发重新呈现,但似乎并非如此。

我尝试使用生命周期方法在LocalizedComponent内部实现localization.jsx作为类,但我注意到shouldComponentUpdate在状态发生变化时甚至不会触发。

我希望LocalizedComponent在所选语言发生变化时自动更新。显然我一定是做错了。

有人可以帮我理解吗?

1 个答案:

答案 0 :(得分:2)

如果您使用React-Redux,则应使用connect方法将组件连接到redux商店。
更新context值不会触发重新呈现的组件 - 当context中的任何内容发生更改时,不会通知React组件。仅当React组件的状态已更改,其父级已重新呈现或已调用forceUpdate时,才会重新呈现React组件。在您的情况下,上下文仅指向充当redux存储的对象,并且React组件不知道此对象中的更改。 此外,你永远不应该更新上下文。根据反应docs

  

不要这样做。

     

React有一个API来更新上下文,但它从根本上被打破了   你不应该使用它。

此外,在React-Redux上下文存储属性始终指向同一个商店对象 - 当状态更新时,只更改了一些内部存储对象属性,但上下文仍保持相同的对象引用,因此实际上下文值不会更改

在调度操作后,当redux状态发生变化时,有两种解决方案可以确保通知和更新组件。

如果您使用React-Redux,则应使用React-Redux connect。根据文档connect返回:

  

传递状态和操作的高阶React组件类   从提供的参数派生到组件中的创建者。

当给定组件使用的状态属性发生更改时,将自动重新呈现连接到存储的组件。

如果您不使用React-Redux,您还可以使用Redux store subscribe方法手动订阅商店更新。根据文档subscribe

  

添加更改侦听器。它会在任何时候被调用   调度,状态树的某些部分可能有   改变。然后,您可以调用getState()来读取当前状态树   在回调中。