Reactjs React/Redux/Immutable-关于带有子组件的HOC策略的混淆
我希望我能以问题的形式理解所有这些。在过去的7个多小时里,我一直在努力解决这个问题,但没有成功。我的大脑在这一点上已经干涸了,不管怎样,我已经走到了死胡同 我正在使用react 15.6.1、redux 3.7.1、react redux 5.0.5、redux immutable 4.0.0、redux form 7.2.0、react select 1.2.1 我的应用程序具有搜索功能,字段A和字段B使用两种不同的表单(不同页面的不同表单)。我不认为这是这个问题的关键,但我正在使用redux表单和react select作为表单和搜索字段。我将用户输入的搜索条件存储在我的搜索缩减器中,以同步不同表单中选择列表的自动填充等 redux表单-->react select(字段A) ---->反应选择(字段B) 我的搜索缩减器正在initialState()中使用Immutable.fromJs()。减速器按预期工作。我的问题是在何处使用HOC,以便将从reducer返回的Map对象转换为react select组件所需的JS数组 MainSearchForm.js:-Reactjs React/Redux/Immutable-关于带有子组件的HOC策略的混淆,reactjs,react-redux,immutability,immutable.js,higher-order-components,Reactjs,React Redux,Immutability,Immutable.js,Higher Order Components,我希望我能以问题的形式理解所有这些。在过去的7个多小时里,我一直在努力解决这个问题,但没有成功。我的大脑在这一点上已经干涸了,不管怎样,我已经走到了死胡同 我正在使用react 15.6.1、redux 3.7.1、react redux 5.0.5、redux immutable 4.0.0、redux form 7.2.0、react select 1.2.1 我的应用程序具有搜索功能,字段A和字段B使用两种不同的表单(不同页面的不同表单)。我不认为这是这个问题的关键,但我正在使用redux
import React, {Component} from 'react'
import { Field, reduxForm } from 'redux-form'
import { connect } from 'react-redux'
import FormFieldA from './FormFieldA'
import FormFieldB from './FormFieldB'
class MainSearchForm extends Component {
render() {
return(
<form>
<FormFieldA options={this.props.fieldAoptions}/>
<FormFieldB options={this.props.fieldBoptions}/>
</form>
)
}
}
function mapStateToProps ({Search}, props) {
return {
fieldAoptions: Search.get('fieldAoptions'),
fieldBoptions: Search.get('fieldBoptions'),
}
}
MainSearchForm = connect(mapStateToProps,{})(MainSearchForm);
export default reduxForm({
form: 'main-search',
})(MainSearchForm)
我可以使用Immutable.toJS()来转换它,但Redux官方指南出于性能原因建议不要这样做,建议使用(我假设是可重用的)HOC组件来解析到JS数组的不可变映射
我的问题是,我将如何将其合并?正如您在上面的代码中所看到的,现在我的MainSearchForm正在连接到Redux存储,以检索作为react select options props选项所需的选项数据。答案是不使用MainSearchForm,而是为MainSearchForm提供的每个字段使用一个中间组件,该中间组件在使用connect之前调用HOC,如指南中所示:-
import React from 'react'
import { Iterable } from 'immutable'
export const toJS = WrappedComponent => wrappedComponentProps => {
const KEY = 0
const VALUE = 1
const propsJS = Object.entries(
wrappedComponentProps
).reduce((newProps, wrappedComponentProp) => {
newProps[wrappedComponentProp[KEY]] = Iterable.isIterable(
wrappedComponentProp[VALUE]
)
? wrappedComponentProp[VALUE].toJS()
: wrappedComponentProp[VALUE]
return newProps
}, {})
return <WrappedComponent {...propsJS} />
}
摘自Redux不可变指南:-
import React from 'react'
import { Iterable } from 'immutable'
export const toJS = WrappedComponent => wrappedComponentProps => {
const KEY = 0
const VALUE = 1
const propsJS = Object.entries(
wrappedComponentProps
).reduce((newProps, wrappedComponentProp) => {
newProps[wrappedComponentProp[KEY]] = Iterable.isIterable(
wrappedComponentProp[VALUE]
)
? wrappedComponentProp[VALUE].toJS()
: wrappedComponentProp[VALUE]
return newProps
}, {})
return <WrappedComponent {...propsJS} />
}
这是最佳做法吗
我将真诚地感谢在这方面的任何帮助。这是我第一次使用HOC&Immutable,它有很多优点。但是我想我终于掌握了这个范例。不要太担心最佳实践,今天的最佳实践就是明天的反模式。不要误解我,知道什么是做事情的“最好”方式是很好的,但最好的方式总是相对的,所以要考虑到这一点 这个想法是,您的FormFieldA和FormFieldB不应该关心可能出现的redux、immutable、foobar、bajouras、WTVlibrary或Tools 因此,对于不可变项,您的HOC应该位于您的MainSearchForm:
import React, {Component} from 'react'
import { Field, reduxForm } from 'redux-form'
import { connect } from 'react-redux'
import { toJS } from './to-js'
import FormFieldA from './FormFieldA'
import FormFieldB from './FormFieldB'
class MainSearchForm extends Component {
render() {
return(
<form>
<FormFieldA options={this.props.fieldAoptions}/>
<FormFieldB options={this.props.fieldBoptions}/>
</form>
)
}
}
function mapStateToProps ({Search}, props) {
return {
fieldAoptions: Search.get('fieldAoptions'),
fieldBoptions: Search.get('fieldBoptions'),
}
}
MainSearchForm = connect(mapStateToProps,{})(toJS(MainSearchForm));
export default reduxForm({
form: 'main-search',
})(MainSearchForm)
FWIW我在所有连接的组件上使用redux文档中的toJS HOC。非常感谢各位。我已经实现了你的代码Fabio,效果不错。当我在这里问你的时候,我已经完全精神崩溃了,非常感谢你。对于其他可能听从Fabio建议的人,请注意,他在connect()内部实现了toJS(),而不是MapStateTrops(),因为后者会妨碍性能,因为如果状态的任何部分发生更改,则会强制重新命名,因为如果转换发生在MapStateTrops()中,React会将状态的所有部分视为新对象。请参阅我在问题中链接的官方Redux文档以供参考。
import { connect } from 'react-redux'
import { toJS } from './to-js'
import FormFieldA from './FormFieldA'
function mapStateToProps ({Search}, props) {
return {
fieldAoptions: Search.get('fieldAoptions'),
}
}
export default connect(mapStateToProps)(toJS(FormFieldA))
import React, {Component} from 'react'
import { Field, reduxForm } from 'redux-form'
import { connect } from 'react-redux'
import { toJS } from './to-js'
import FormFieldA from './FormFieldA'
import FormFieldB from './FormFieldB'
class MainSearchForm extends Component {
render() {
return(
<form>
<FormFieldA options={this.props.fieldAoptions}/>
<FormFieldB options={this.props.fieldBoptions}/>
</form>
)
}
}
function mapStateToProps ({Search}, props) {
return {
fieldAoptions: Search.get('fieldAoptions'),
fieldBoptions: Search.get('fieldBoptions'),
}
}
MainSearchForm = connect(mapStateToProps,{})(toJS(MainSearchForm));
export default reduxForm({
form: 'main-search',
})(MainSearchForm)
import React, {Component} from 'react'
import FormFieldA from './FormFieldA'
import FormFieldB from './FormFieldB'
class MainSearchForm extends Component {
render() {
return(
<form>
<FormFieldA options={this.props.fieldAoptions}/>
<FormFieldB options={this.props.fieldBoptions}/>
</form>
)
}
}
export default MainSearchForm
import { Field, reduxForm } from 'redux-form'
import { connect } from 'react-redux'
import MainSearchForm from './MainSearchForm'
import { toJS } from './to-js'
function mapStateToProps ({Search}, props) {
return {
fieldAoptions: Search.get('fieldAoptions'),
fieldBoptions: Search.get('fieldBoptions'),
}
}
const MainSearchFormContainer = connect(mapStateToProps,{})(toJS(MainSearchForm));
export default reduxForm({
form: 'main-search',
})(MainSearchFormContainer)