在 React 和 Redux 中重新渲染所有组件

Re-render all components in React and Redux

我有简单的应用程序:

import React, { Component } from 'react';
import MainPage from './MainPage';
import { setLanguage, currentLanguage, availableLanguages } from '../localization';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as appActions from '../actions/appActions';
class App extends Component {
  constructor(props) {
    super(props);
  }
  componentDidMount() {
    $('.dropdown-button').dropdown();
  }
  setLanguageHandle(twoLetter, e) {
    e.preventDefault();
    setLanguage(twoLetter);
  }
  render() {
    return (
      <div>
        <ul id='languageDropdown' className='dropdown-content'>
          {availableLanguages().map((item, i) =>
            <li key={i}><a href='' onClick={this.setLanguageHandle.bind(this, item.twoLetterISOLanguageName)}>{item.nativeName}</a></li>
            )}
        </ul>
        <nav className='cyan'>
          <div className='nav-wrapper'>
            <a className='brand-logo' style={{ marginLeft: 16 }}>SUPP</a>
            <ul className='right hide-on-med-and-down'>
              <li>
                <a className='dropdown-button' href='' data-activates='languageDropdown'>
                  {currentLanguage().nativeName}
                  <i className='material-icons right'>arrow_drop_down</i>
                </a>
              </li>
            </ul>
          </div>
        </nav>
        <div className='container'>
          <MainPage />
        </div>
        <footer className='page-footer cyan'>
          <div className='footer-copyright'>
            <div className='container'>
              <span style={{ fontWeight: 'normal' }}>© 2017</span>
            </div>
          </div>
        </footer>
      </div>
    )
  }
}

function mapStateToProps() {
  return {
  }
}

function mapDispatchToProps(dispatch) {
  return {
    appActions: bindActionCreators(appActions, dispatch)
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App)

这里有简单的本地化下拉菜单,我在其中单击语言,然后它会触发 setLanguageHandlesetLanguage 来自 ../localization 使用 cookie 设置语言。

MainPage 组件及其子组件从 Redux 加载它们的所有属性。本地化是唯一的例外,看起来像 _localize('sometext'),它使用:

export function _(key) {
    let currentCulture = getCurrentCultureFromCookie();
    let translation = translations[currentCulture]['translations'][key];
    return translation;
}

因此,在本地化中没有使用 Redux。

问题是,当我改变文化时,子组件不会重新呈现。我试图调用我的合成 Redux 动作,它改变了存储中的一个自变量,但没有重新渲染,似乎做这样的工作太聪明了。

当我调用 setLanguageHandler 以提供即时文化切换时,如何重新呈现整个应用程序中的所有组件?也许有另一种方法可以在不重新加载整个页面的情况下做到这一点?

我认为最好的方法是使用 redux 进行本地化。具体来说,我认为您应该将 "currentCulture" 放入您的商店。然后将对“_localize”方法的调用替换为可能如下所示的 Localize 组件:

import React from "react";
import { connect } from "react-redux";

function Localize(props) {
    return (
        <span>{translations[props.currentCulture]['translations'][props.textKey]}</span>
    );
}

const mapStateToProps = (state) => {
  return {currentCulture: state.currentCulture};
};
const LocalizeContainer = connect(mapStateToProps)(Localize);
export default LocalizeContainer;

然后您可以将其与类似的东西一起使用:

<Localize textKey="sometext" />

我意识到这是方法上的一个重大变化,但我认为让部分渲染由不在您的状态下的变量控制是在自找麻烦。

可以更灵活地使用(例如在 属性 值中)的 alternative/complementary 方法是一个容器,它注入一个 "localize" 方法作为 属性包装的组件。

在 "localize.js":

import { connect } from "react-redux";

const localizeText = currentCulture => textKey => { return translations[currentCulture]['translations'][textKey]; };

const mapStateToProps = (state) => {
  return { localize: localizeText(state.currentCulture) };
};

export default function localize(LocalizedComponent) {
  return connect(mapStateToProps)(LocalizedComponent);
}

然后使用它:

import React from "react";
import localize from "./localize.js"

function YourDisplayComponent(props) {
    return (
        <input value={props.localize(props.inputValueKey)}>
    );
}
export default localize(YourDisplayComponent);