将嵌套的 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
}
这是您要找的吗?
与 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
}
这是您要找的吗?