javascript - React 中的高阶组件 (HOC) 导致包装组件的额外渲染
问题描述
我HOC
用来包装所有应该有翻译的组件。每个组件都有其动态导入的翻译文件。他们还共享一些共享功能。所以,我创建了HOC
,这是一个以组件为参数的函数,返回组件具有一些额外的功能(例如修改componentDidMount
)。
下面是App.js
和Translate.js
( HOC
)。
应用程序.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 ;
翻译.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
'sstate
中,然后通过props
. 被包装的组件接收传递props
并将其保存到state
(in 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
如果我对重复代码做同样的事情(在每个组件中定义逻辑)
应用程序.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.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
因此,我有额外的渲染,因为我将作为道具的翻译放入组件状态。为什么?因为他们来async。所以我有一个选择:要么在组件中编写一些逻辑来检查翻译是否已经到达,如果没有,则有一些后备选项,或者等到它们来并在我的组件state
中安全地使用它们。App
我错过了什么或做错了吗?或者这是正常的行为HOC
?也许Redux
可以解决这个问题。
解决方案
推荐阅读
- postgresql - 如何在 Postgres 中存储社交媒体 Unix 时间戳,保留用户的本地时间
- scala - Gatling - 如何在 Scala 中设置 Gatling 控制台日志级别
- java - 在 call() 方法的返回语句执行之前具有对象引用的未来对象
- javascript - TinyMCE 在编辑器中显示错误
- javascript - 是否可以使用 `require.context` 为 Webpack 进行动态导入?
- spring - Spring中原型bean的@component和@scope之间的区别
- google-chrome - 内嵌 Chrome 扩展程序下载不会添加到网上商店计数中
- selenium - 在调用另一个函数期间,我在线程“main”java.lang.NullPointerException 中收到“timeoutException”
- delphi - Delphi 使用 ScaleBy 和 Margin 进行缩放
- amazon-web-services - [亚马逊](500310) 无效操作:溢出(长有效范围 -9223372036854775808 到 9223372036854775807)