2017-02-01 3 views
1

У меня есть простое приложение:пересборку все компоненты в React и 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) 

Здесь у меня есть простой локализации выпадающий список, где я нажав на языке, то он стреляет setLanguageHandle. setLanguage от ../localization использует cookie для установки языка.

MainPage Компонент и его дети загружают все свои свойства из Редукса. Локализация является единственным исключением и выглядит _localize('sometext'), которая использует:

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

так, не Redux не используется в локализации.

Проблема в том, что когда я меняю культуру, компоненты для детей не перерисовываются. Я попытался назвать свое синтетическое действие Redux, которое меняет одну независимую переменную в магазине, но ничего не перерисовывает, кажется, слишком умна для такого рода работы.

Как я могу повторно отобразить все мои компоненты во всем приложении, когда я звоню setLanguageHandler, чтобы обеспечить коммутацию культуры на лету? Может быть, есть еще один способ для таких вещей, сделать это, не перезагружая всю страницу?

+0

Вы пробовали [forceUpdate()] (https://facebook.github.io/react /docs/react-component.html#forceupdate)? –

+0

@NikolajDamLarsen Да, он только обновляет компонент приложения, он не влияет на детей App. –

ответ

1

Я считаю, что наилучшим подходом было бы использовать сокращение для локализации. В частности, я думаю, вы должны положить «currentCulture» в свой магазин. Затем замените вызовы на метод «_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" /> 

Я понимаю, что это существенное изменение подхода, но я думаю, что вы просите головные боли, имея части вашего рендеринга, которые контролируются переменной, которая не находится в вашем состоянии.

Альтернативный подход, который может использоваться более гибко (например, в значениях свойств), будет контейнером, который внедряет метод «локализовать» как свойство обернутого компонента.

В "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); 
+0

Кажется, хорошо, но что нам делать, если мы хотим локализовать что-то вроде ''? –

+0

Я добавил к своему ответу альтернативный подход, в котором рассматривается вариант использования локализации значений свойств. –

+0

Насколько я понимаю, со вторым методом нам просто нужно обернуть компонент, где мы хотим использовать локализацию в 'localize' функции? Как мы должны обернуть уже завернутые компоненты, например. г. 'экспорт по умолчанию connect (mapStateToProps, mapDispatchToProps) (приложение)'? –

Смежные вопросы