将存储手动传递给组件时组件不重新渲染(react-redux)

时间:2017-08-25 05:24:49

标签: reactjs react-redux

我正在构建一个动态呈现来自json定义的反应组件的应用程序。某些组件需要使用数据上下文进行渲染。然后,这些组件需要获取外部数据。我之前有一个天真的解决方案,用DataComponent包装这些组件,在挂载期间触发请求然后设置状态。这种方法很有效。

componentWillMount = () =>
  provider
    .get()
    .then(data => this.setState({data}))

现在,我尝试使用redux提出一个解决方案,这样所有数据模式都会有一个reducer,每个组件都不需要管理自己的数据(可能来自与其他组件相同的源)。存储已正确初始化,我可以看到每当调度一个动作时,存储状态都会正确更新(我使用redux devtools进行验证,没有状态发生变化)。但是,组件不会使用新数据进行更新。初始调用后不会重新调用render函数。

这是与我提出的类似的代码:

import React from 'react'
import {connect} from 'react-redux'
import PropTypes from 'prop-types'

// Component: React.Component
// store: redux-store
// schema: String
export default function connectedComponent(Component, store, schema) {

    class DataComponent extends React.Component {

        static propTypes = {
            // eslint-disable-next-line react/forbid-prop-types
            data: PropTypes.any
        }

        static defaultProps = {
            data: null
        }

        render = () => {
            if (this.props.data) {
                return this.renderComponent(Component, this.props.data)
            }
            return (<span>empty</span>)
        }

    }

    renderComponent = (Component, data) => ...

    // eslint-disable-next-line react/no-multi-comp,react/display-name
    return (props) => {
        const ConnectedData = connect(mapStateToProps(schema))(DataComponent)
        return (
            <ConnectedData {...props}
                           store={store}/>)
    }
}

const mapStateToProps = (schema) => (state) => ({
    data: state[schema][schema]
})

这是商店的代码

import {createStore} from 'redux'
import {combineReducers} from 'redux'
import reduce from 'lodash/reduce'
import has from 'lodash/has'

export default (schemas) => createStore(
    createReducers(schemas),
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)

const createReducers = (schemas) => combineReducers(reduce(schemas, accumulateReducers, {}))

const accumulateReducers = (reducers, schema) => ({...reducers, [schema.id]: createReducer(schema)})

const createReducer = (schema) => {
    return (state = getDefault(schema), {type, response}) => {
        switch (type) {
            case `${schema.id}_GET_SUCCESS`:
                return {...state, [schema.id]: response}
            default:
                return state
        }
    }
}

const getDefault = (schema) => ({
    [schema.id]: getDefaultValue(schema)
})

const getDefaultValue = (schema) => {
    if (has(schema, 'defaultValue')) {
        return schema.defaultValue
    }

    switch (schema.type) {
        case 'array':
            return []
        case 'object':
            return {}
        default:
            return null
    }
}

在应用程序内部,还有另一个redux存储来管理渲染器状态。

编辑1: 添加github repo来演示问题 https://github.com/clydeespeno/redux-custom-store

编辑2: react-redux版本是5.0.2,发现有一个与自定义商店订阅相关的错误,已经至少在5.0.6上修复了

1 个答案:

答案 0 :(得分:0)

react-redux版本是5.0.2,发现有一个与自定义提供的商店订阅相关的错误,已经至少在5.0.6上修复了

将react-redux更新为5.0.6解决了这个问题。这里描述了错误https://github.com/reactjs/react-redux/pull/589