我开始在React中使用Redux,我非常喜欢它。但是,我目前遇到的问题是,除了状态之外,我还需要在整个应用程序中存储/使用更多信息。
在这种特定情况下,我有一个模型,其状态是从API获取的。该模型还有一些关于自身的信息,例如如何在屏幕上显示属性“name”=> “blabla的名字”。我理解如何使用Redux来处理状态,但是我很难看到我还需要在整个应用程序中传播但实际上并不是状态的其他信息。
答案 0 :(得分:12)
据Redux说,国家是唯一的真相来源"。它不应该有重复(这会导致不一致)。
因此,您的州应该存储name
,而不是计算标签属性。
确实," blabla的名字"是一个函数(在数学意义上),你的名字值,如果它们不同(例如,如果在某些时候名称===' foo'但标签是'栏的名称& #39;而不是foo'的名称,那么你有问题...
所以我要做的就是在你的状态中存储最小值(在这种情况下为名称),并直接在Component中计算标签,你需要它。
如果您需要重复使用它,那么创建一个仅将您的名字作为道具的组件,并使用" blablaba的名称"呈现一个字符串。 (如果我认为名字= blabla)。
如果你需要更复杂的计算(比如你有多个标签,日期计算等),你总是可以创建一个函数来输入你的状态,并吐出你的模型"在输出中计算所有内容。
Redux本质上非常实用,所以你不妨接受它:)
答案 1 :(得分:6)
我知道我迟到了,但我觉得有人可能会回答这个问题。在与React合作多年后,对我来说有用的是建立一个类似这样的结构:
所以说我的应用流程是这样的:
调度ACTION
=>如果该操作是异步的,则SAGA
正在侦听并执行获取操作=>此传奇保存了对STATE
=>的更新。 [从现在开始反应组件层] =>如果我的观点需要来自我的州的数据以不同的格式出于任何原因我通过SELECTOR
发送它将改变格式=>然后我将这个新的解析数据附加到我的容器组件。
其他流程可能是您需要不在state
中的静态数据的流程。在那个原因我将它保存在一个单独的文件中的对象中,并将其直接导入我的容器组件(我从不直接导入我的子/表示组件中的任何东西。只有其他组件。数据处理在一个单独的层而不是组件)。
我现在能想到的第三种流程是当你需要对你的API进行POST时,无论出于何种原因,你所在州的数据需要进行一些解析才能这样做。在这种情况下,我会在第一个例子中做同样的事情,但反过来说:派遣ACTION
=>由SAGA
=>处理在进行提取之前,我会为我的POST提供已经构建的数据(sagas有一个名为select
的方法来帮助你在这里使用选择器)=>然后我会执行异步操作=>相应地更新状态。
万一你不知道我的意思是选择者或传说中的一些链接:
答案 2 :(得分:1)
我认为对于基于Redux的应用程序而言,模型与任何其他系统一样必要。
模型是系统的词汇。模型为代码库带来了理智。没有它们,代码库就像是一系列疯狂的扭曲思想。
您可以使用状态函数来满足ReactJS + Redux应用程序中模型的需要。 就像模型包含数据和方法一样,这些对象只包含可以应用于状态的函数。
请在此处阅读:https://medium.com/@nshnt/state-functions-for-modeling-with-redux-a9b9d452a631。
这是着名的具有状态函数的Redux TODO应用程序示例:
todo_reducer.js:
import TODO from './todo_state';
const todoListReducer = (state=TODO.initialState(), action)=>{
switch(action.type){
case 'ADD_TODO' :
return TODO.addTask(state, action.taskName);
case 'FINISHED_TODO':
return TODO.setFinished(state, action.taskID );
case 'PENDING_TODO':
return TODO.setPending(state, action.taskID );
default :
return state;
}
};
export default todoListReducer;
todo-state.js:
export default {
initialState: () => [],
addTask: (todoList, name)=> todoList.concat({id: todoList.length, name: name}),
setFinished: (todoList, taskId) => (
todoList.map(task=> task.id === taskId ? {...task, complete: true} : task)
),
setPending: (todoList, taskId) => (
todoList.map(task=> task.id === taskId ? {...task, complete: false} : task)
),
pending: todoList=> todoList.filter(task=> !task.complete)
};
如果组件需要对状态进行一些操作,我也会在组件中使用这些状态函数。
todo_list.js:
import React from 'react';
import {connect} from 'react-redux';
import TODO from './todo_state';
const TodoList = ({tasks, showCompletedTasks, toggleTodo})=> {
const toListElement = (task) => (
<li key={task.id}>
<input type="checkbox" checked={task.complete} onChange={(e)=> toggleTodo(task)}/>
<label>{task.name} {task.complete ? "Complete" : "Pending"}</label>
</li>
);
const visibleTaskList =
(showCompletedTasks ? tasks
: TODO.pending(tasks)).map(toListElement);
return (
<ul className="todo-list">
{visibleTaskList}
</ul>
);
}
.....
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);
答案 3 :(得分:0)
Reselect是位于您应用中的简单库。它的主要功能是聚合来自Redux存储的数据。
取自https://medium.com/@parkerdan/react-reselect-and-redux-b34017f8194c
import { createSelector } from 'reselect'
// selector
const getBar = (state) => state.foo.bar
// reselect function
export const getBarState = createSelector(
[ getBar ],
(bar) => bar
)
这个想法是,您将组件与redux-connect
或map state to props
连接,但不是直接使用商店,而是将商店传递给选择器。该选择器将具有一项功能,可让您聚合数据或以任意方式对其进行转换。
import React from 'react'
import { connect } from 'react-redux'
import { getBarState } from '../selectors'
const mapStateToProps = (state) => {
return {
bar: getBarState(state)
}
}
这种方法的优点是您可以很容易地在任何组件上重用选择器。您可以在数据到达组件(Separation of concerns principal)之前对其进行操作。这为您带来2大优势。
重新选择可帮助您的React应用变得更加结构化。