Я использую HOC, чтобы обернуть все компоненты, которые должны иметь переводы. У каждого компонента есть свой файл перевода, который импортируется динамически. Также они разделяют некоторые общие функции. Итак, я создал HOC, функцию, принимающую компонент в качестве аргумента, возвращающего компонент с некоторыми дополнительными функциями (например, модифицированный componentDidMount).
Ниже представлены App.js и Translate.js (HOC).
App.js
import React, { Component } from 'react';
import translated from './Translate';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
translation: {
a: '',
},
translationRecieved: false
}
}
componentDidMount() {
console.info('APP mounted')
}
componentDidUpdate() {
console.info('APP did update')
if (!this.state.translationRecieved) {
this.setState({
translation: this.props.translation,
translationRecieved: true
})
}
}
render() {
console.info('APP renders')
const { t } = this.props
const { a } = this.state.translation
return (
<div className = "App">
<p>This is state: a is {a}</p>
<hr/>
<p>Translated `a` is {t(a)}</p>
</div>
);
}
}
const Apptranslated = translated(App);
export default Apptranslated ;
Translate.js
import React from 'react';
import en from './en.json';
const translated = (WrappedComponent) => {
class HOC extends React.Component {
constructor(props) {
super(props);
this.state = {
translation: null
}
}
componentDidMount() {
console.info('HOC mounted')
this.setState({
translation: en
})
}
componentDidUpdate () {
console.info('HOC did update')
}
translate = (val = '') => `**| ${val} |**`;
render() {
console.info('HOC renders')
return <WrappedComponent
translation = {this.state.translation} t = {this.translate} {...this.props}/>;
}
}
return HOC;
};
export default translated;
Вместо того, чтобы определять логику загрузки трансляции в каждом компоненте, я использовал HOC. HOC загружает переводы в HOCstate и затем передает их обернутому компоненту через механизм props. Обернутый компонент получает переданный props и сохраняет его на state (в componentDidUpdate). Итак, мои жизненные циклы:
HOC renders
APP renders
APP mounted
HOC mounted
----initial phase ended---
----HOC fetched resources---
HOC renders
APP renders
APP did update
HOC did update
----APP modifies its state---
APP renders
APP did update
Если бы я сделал то же самое с повторяющимся кодом (определяя логику в каждом компоненте)
App.js
import React, { Component } from 'react';
import en from './en.json';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
translation: {
a: '',
},
translationRecieved: false
}
}
componentDidMount() {
console.info('APP mounted')
if (!this.state.translationRecieved) {
this.setState({
translation: en,
translationRecieved: true
})
}
}
componentDidUpdate() {
console.info('APP did update')
}
translate = (val = '') => `**| ${val} |**`;
render() {
console.info('APP renders')
const { a } = this.state.translation
return (
<div className = "App">
<p>This is state: a is {a}</p>
<hr/>
<p>Translated `a` is {this.translate(a)}</p>
</div>
);
}
}
export default App;
я бы получил
APP renders
APP mounted
APP renders
APP did update
Таким образом, у меня есть дополнительный рендеринг, потому что я помещаю переводы, поступающие как реквизиты, в состояние компонента. Почему? Потому что они приходят асинхронный. Итак, у меня есть выбор: либо написать некоторую логику в компоненте, чтобы проверить, поступили ли переводы, и если у них нет резервных вариантов, либо подождать, пока они появятся, и использовать state, чтобы безопасно использовать их в моем компоненте App.
Я что-то упускаю или делаю неправильно? Или это нормальное поведение HOC?
Возможно, Redux может решить эту проблему.
Я добавил код. Какие методы позволяют отложить рендеринг? Считается ли это плохой практикой?
Я представляю, if (!a) return null; изнутри render()
@EdwardSammutAlessi, это решило мою проблему. Спасибо!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если переводы загружаются асинхронно, у вас действительно нет особого выбора. Вы не можете отложить рендеринг, поэтому либо вы откладываете рендеринг, пока у вас не будет все, либо вы рендерите заполнитель.