React Redux 的通用组件
Generic Components with React Redux
我对 redux 中的全局状态和可重用组件的概念有点纠结。
假设我有一个文件选择器组件,我想在我的应用程序状态中的多个位置使用它。创建 action/reducers 会导致大量膨胀,因为我必须处理带有动态后缀的状态和其他奇怪的事情,这些事情并没有真正让我觉得这是一种聪明的处理方式。
关于这些事情的普遍共识是什么?我只能看到两个解决方案:
使文件选择器组件具有本地状态(this.setState/this.getState
)
使文件选择器成为全局状态的一部分,但在它自己独特的减速器中,我可以在组件操作完成后从中读取?
有什么想法/最佳做法吗?谢谢
更新:澄清一下我描述的文件选择器不是一个简单的组件,它纯粹在客户端工作,但必须从服务器获取数据,还提供分页如过滤等。这就是为什么我还想重用大部分 client/server 交互。显示此组件的视图当然是愚蠢的,只显示来自状态的值 - 但我如何在应用程序周围的多个位置重用 actions/reducers?
通常,经验法则是您使用 redux store
来管理应用程序中的数据,也就是存储从服务器获取的项目和本地 react state
用于 ui 行为,例如在你的情况下文件上传。我会制作一个纯反应组件来管理文件上传,然后使用 redux-form 来管理特定的表单。
下面是我在项目中使用的组件示例
import React, {Component, PropTypes} from 'react';
import Button from 'components/Button';
class FileButton extends Component {
static propTypes = {
accept: PropTypes.string,
children: PropTypes.any,
onChange: PropTypes.func.isRequired
};
render() {
const {accept, children, onChange} = this.props;
return <Button {...this.props} onClick={() => this.file.click()}>
<input
ref={el => this.file = $(el)}
type="file"
accept={accept}
style={{display: 'none'}}
onChange={onChange}
/>
{children}
</Button>;
}
}
export default FileButton;
我们得出结论,可重用组件必须有两种:
哑组件,即仅接收道具并仅通过道具回调触发 "actions" 的组件。这些组件具有最小的内部状态或根本没有。这些是最常见的可重用组件,您的文件选择器可能会属于这种情况。样式化的文本输入或自定义列表也是很好的例子。
提供自己的动作和减速器的连接组件。这些组件在应用程序中有自己的生命,并且独立于其他组件。一个典型的例子是 "top error message box",它在应用程序严重失败时显示在其他所有内容之上。在这种情况下,应用程序会触发一个 "error action" 并将适当的消息作为有效负载,并且在接下来的重新呈现中,消息框会显示在其余部分之上。
让你的减速器处理你的组件状态的多个实例。当您的 FileBrowser 组件出现在应用程序中时,只需为它的每个实例定义一些 "unique" ID,并将您的当前状态包装在一个对象中,并将此 uniqueIds 作为键,并将您的旧复杂状态作为值。
这是我多次使用的技巧。如果您的所有 FileBrowser 在编译时都是已知的,您甚至可以在 运行 您的应用程序之前设置初始状态。如果您需要支持 "dynamic" 个实例,只需创建一个 Action 来初始化给定 id 的状态。
您没有提供任何代码,但这里有一个可重复使用的 Todo reducer 的人为示例:
function todos(state={}, action){
switch(action.type){
case 'ADD_TODO':
const id = action.todoListId
return {
...state,
[id]: {
...state[id],
todos: [ ...state[id].todos, action.payload ]
}
}
// ...
}
}
我对 redux 中的全局状态和可重用组件的概念有点纠结。
假设我有一个文件选择器组件,我想在我的应用程序状态中的多个位置使用它。创建 action/reducers 会导致大量膨胀,因为我必须处理带有动态后缀的状态和其他奇怪的事情,这些事情并没有真正让我觉得这是一种聪明的处理方式。
关于这些事情的普遍共识是什么?我只能看到两个解决方案:
使文件选择器组件具有本地状态(
this.setState/this.getState
)使文件选择器成为全局状态的一部分,但在它自己独特的减速器中,我可以在组件操作完成后从中读取?
有什么想法/最佳做法吗?谢谢
更新:澄清一下我描述的文件选择器不是一个简单的组件,它纯粹在客户端工作,但必须从服务器获取数据,还提供分页如过滤等。这就是为什么我还想重用大部分 client/server 交互。显示此组件的视图当然是愚蠢的,只显示来自状态的值 - 但我如何在应用程序周围的多个位置重用 actions/reducers?
通常,经验法则是您使用 redux store
来管理应用程序中的数据,也就是存储从服务器获取的项目和本地 react state
用于 ui 行为,例如在你的情况下文件上传。我会制作一个纯反应组件来管理文件上传,然后使用 redux-form 来管理特定的表单。
下面是我在项目中使用的组件示例
import React, {Component, PropTypes} from 'react';
import Button from 'components/Button';
class FileButton extends Component {
static propTypes = {
accept: PropTypes.string,
children: PropTypes.any,
onChange: PropTypes.func.isRequired
};
render() {
const {accept, children, onChange} = this.props;
return <Button {...this.props} onClick={() => this.file.click()}>
<input
ref={el => this.file = $(el)}
type="file"
accept={accept}
style={{display: 'none'}}
onChange={onChange}
/>
{children}
</Button>;
}
}
export default FileButton;
我们得出结论,可重用组件必须有两种:
哑组件,即仅接收道具并仅通过道具回调触发 "actions" 的组件。这些组件具有最小的内部状态或根本没有。这些是最常见的可重用组件,您的文件选择器可能会属于这种情况。样式化的文本输入或自定义列表也是很好的例子。
提供自己的动作和减速器的连接组件。这些组件在应用程序中有自己的生命,并且独立于其他组件。一个典型的例子是 "top error message box",它在应用程序严重失败时显示在其他所有内容之上。在这种情况下,应用程序会触发一个 "error action" 并将适当的消息作为有效负载,并且在接下来的重新呈现中,消息框会显示在其余部分之上。
让你的减速器处理你的组件状态的多个实例。当您的 FileBrowser 组件出现在应用程序中时,只需为它的每个实例定义一些 "unique" ID,并将您的当前状态包装在一个对象中,并将此 uniqueIds 作为键,并将您的旧复杂状态作为值。
这是我多次使用的技巧。如果您的所有 FileBrowser 在编译时都是已知的,您甚至可以在 运行 您的应用程序之前设置初始状态。如果您需要支持 "dynamic" 个实例,只需创建一个 Action 来初始化给定 id 的状态。
您没有提供任何代码,但这里有一个可重复使用的 Todo reducer 的人为示例:
function todos(state={}, action){
switch(action.type){
case 'ADD_TODO':
const id = action.todoListId
return {
...state,
[id]: {
...state[id],
todos: [ ...state[id].todos, action.payload ]
}
}
// ...
}
}