我正在使用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.log('APP mounted')
}
componentDidUpdate() {
console.log('APP did update')
if(!this.state.translationRecieved) {
this.setState({
translation: this.props.translation,
translationRecieved: true
})
}
}
render() {
console.log('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.log('HOC mounted')
this.setState({
translation: en
})
}
componentDidUpdate () {
console.log('HOC did update')
}
translate = (val = '') => `**| ${val} |**`;
render() {
console.log('HOC renders')
return <WrappedComponent
translation={this.state.translation} t={this.translate} {...this.props}/>;
}
}
return HOC;
};
export default translated;
我使用HOC
来代替在每个组件中加载翻译的定义逻辑。 HOC
将翻译加载到HOC
的{{1}}中,然后通过state
的机制将其传递给包装的组件。包装的组件接收传递的props
并将其保存到props
(在state
中)。所以我的生命周期是:
componentDidUpdate
如果我对重复代码做同样的事情(定义每个组件中的逻辑)
App.js
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
我会得到
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.log('APP mounted')
if(!this.state.translationRecieved) {
this.setState({
translation: en,
translationRecieved: true
})
}
}
componentDidUpdate() {
console.log('APP did update')
}
translate = (val = '') => `**| ${val} |**`;
render() {
console.log('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
可以解决此问题。