将嵌套的 Redux 智能组件与 reducer 连接起来

Connecting nested Redux smart components with reducers

与 Redux 的 ToDo 示例类似,我的项目结构也类似——只是一个容器,其中包含要显示的子组件数组。该商店将如下所示:

{
    workspace: {
        widgets: [1, 2, 3]
    }
    widgets: {
        1: {
            id: 1,
            title: 'First Widget',
            lastPrice: 123.324,
            lastUpdate: '2015-11-12'
        },
        2: {
            id: 2,
            title: 'Second Widget',
            lastPrice: 1.624,
            lastUpdate: '2015-11-12'
        },
        3: {
            id: 3,
            title: 'Third Widget',
            lastPrice: 4.345,
            lastUpdate: '2015-11-12'
        }
    }
}

每个小部件项目本身就是一个复杂的组件 - 许多可能的操作、许多属性和许多子哑组件。因此,我让每个小部件都成为一个连接的智能组件,带有专用的 WidgetReducer 以保持这些状态更改独立。

我希望 WidgetReducer 一次只关注一个小部件,因此它处理的状态将只是一个单独的小部件节点,例如:

{   id: 3,
    title: 'Third Widget',
    lastPrice: 4.345,
    lastUpdate: '2015-11-12'
}

我的 Workspace 组件当前遍历所有 Widget,将 Widget ID 传递给每个 Widget 智能组件:

@connect(state => ({ workspace: state.workspace }))
export default class Workspace extends React.Component {
    render() {
        return (
            <div>
                {this.props.workspace.widgets.map(id =>
                    (<Widget key={id} widgetId={id} />)
                )}
            </div>
        );
    }
}

我的Widget组件是这样的:

@connect((state, ownProps) => ({ widget: state.widgets[ownProps.widgetId]}))
export default class Widget extends React.Component {
    componentWillMount() {
        this.props.dispatch(subscribeToUpdates(this.props.widgetId));
    }

    render() {
        return (
            <div>
                <header>{this.props.widget.title}</header>
                <div> /* Other widget stuff goes here */</div>
            </div>
        );
    }
}

如何连接每个 Widget 组件,使其仅接收其自己的 Widget 对象的状态更新,并且连接的 Widget Reducer 仅关注单个 Widget 对象,而不是它们的集合?

首先看一下Reselect: https://github.com/rackt/reselect

如果我理解这个问题,这就是您要查找的内容。 假设 widget-id 2 的状态发生变化,widget 1 和 widget 3 不关心 widget-id 2 的状态发生变化。只有小部件 2 需要反映该更改。 Reselect 赋予您构建 'memoized' select 函数的能力。这听起来像是一个花哨的词,但实际上它意味着只有当 selector 的输入值发生变化时,它才会计算下一个状态。

在小部件示例中,您将构建 select 函数,这些函数仅在它所关注的状态片段发生变化时才重新计算状态。

可能的例子:

import { createSelector } from 'reselect'

const widgetByIdSelector = (state, props) => state.widgets[props.widgetId]
// this is the `input` function for you selector: as input we take the   
// specific slice of state a specific widgetId requests.
// the main idea is: only if the `input` of this function changes, it'll 'reselect' that state.

export const widgetSelector = createSelector(
   widgetByIdSelector,
    (widgetById) => { 
         return { widgetById } 
   }

@connect(widgetSelector)
export default class Widget extends Component { ... }

我不知道这段代码是否有效,是在互联网连接不稳定的火车上写的,但这是主要想法...

对于 reducer 和 action creators(你可能会做这样的事情):

export function createActionForSpecificWidgetById(widgetId, payload) {
    return {
       type: ACTIONS.HERE_COMES_YOUR_ACTION_TYPE,
       widgetId,
       payload
    }
}

function reducer(state = initialState, action) {
  switch(action.type) {
  case HERE_COMES_YOUR_ACTION_TYPE:
      //now you can modify the state of the specific widgetId because you have access to the id at action.widgetId
}

这是您要找的吗?