将 Redux 添加到现有的 React 应用程序
Adding Redux to an existing React app
我一直在开发 React 应用程序,并且已经到了需要 Redux 来处理它的某些方面的地步。
阅读了一堆教程后,我对如何制作我的 "smarter" 组件 "dumber" 以及如何将函数移动到我的动作和 reducer 中非常困惑。
因此,例如,应用程序的一个方面更像是待办事项列表样式。
我的一个 类 是这样开始的:
export default class ItemList extends React.Component {
constructor() {
super();
this.state = { items: [],
completed: [],
};
this.addItem = this.addItem.bind(this);
this.completeItem = this.completeItem.bind(this);
this.deleteItem = this.deleteItem.bind(this);
}
addItem(e) {
var i = this.state.items;
i.push({
text: this._inputElement.value,
paused: false,
key: Date.now()
});
this.setState({ items: i });
e.preventDefault();
this._inputElement.value = '';
this._inputElement.focus();
}
completeItem(e) {
this.deleteItem(e);
var c = this.state.completed;
c.push({
text: e.target.parentNode.parentNode.getElementsByClassName('item-name')[0].innerHTML,
paused: false,
key: Date.now()
});
this.setState({ completed: c });
}
deleteItem(e) {
var i = this.state.items;
var result = i.filter(function(obj) {
return obj.text !== e.target.parentNode.parentNode.getElementsByClassName('item-name')[0].innerHTML;
});
this.setState({ items: result });
}
// ... more irrelevant code here ...
// there's a function called createTasks that renders individual items
render() {
var listItems = this.state.items.map(this.createTasks);
return <div className="item-list">
<form className="form" onSubmit={this.addItem}>
<input ref={(a) => this._inputElement = a}
placeholder="Add new item"
autoFocus />
<button type="submit"></button>
</form>
{listItems}
</div>;
}
}
因此,如您所见,它非常注重逻辑。我已经开始通过在我的索引文件中添加一个 <Provider>
来添加 Redux,并制作了一个到目前为止相当空的基本 reducers 文件:
import { combineReducers } from 'redux';
const itemList = (state = {}, action) => {
};
// ... other irrelevant reducers
const rootReducer = combineReducers({
itemList,
// ...
});
export default rootReducer;
...我制作了一个动作文件,其中也没有太多内容。
我一直在苦苦思索:
- 我见过的大多数操作只是 return 某种 JSON 的示例,我在使用我的组件 JSON 的减速器中 return 做什么可以用吗?
- 我的组件逻辑有多少是可重用的,还是我应该忘记它?尽可能多地重用我编写的代码的最佳方法是什么?
首先你需要了解redux如何与react一起工作的全貌。
在开始之前,让我们先了解一下什么是智能组件和哑组件。
智能组件
- 你所有的代码逻辑都需要在这里处理
- 它们也被称为容器。
- 他们与商店交互(也称为状态管理)以更新您的组件。
哑组件
- 他们只是从你的容器中读取道具并渲染你的组件
- 这只是 UI 视图,不应包含任何逻辑。
- 所有 styling/html/css 都在您的哑组件中。
Here 是一篇很棒的文章,如果您仍然有疑问,可以阅读它来理解聪明和愚蠢的组件。
好的,现在让我们试着理解 redux 是如何工作的:-
- 您的智能组件(又名容器)与您的 redux 存储交互
- 你从你的容器中触发动作。
- 你的行为叫你的api
- 您的操作结果通过减速器更新商店
- 您的容器通过 mapStateToProps 函数读取商店,一旦商店中的值发生变化,它就会更新您的组件。
现在让我们考虑一下您的待办事项示例
TodoListContainer.js
class TodoListContainer extends Component {
componentWillMount () {
// fire you action action
}
render () {
return (
<Todos todos=={this.props.todos} />
)
}
}
function mapStateToProps(state) {
const {todos} = state;
return {
todos;
}
}
export default connect(mapStateToProps)(TodoListContainer)
TodoList.js
class TodoList extends Component {
renderTodos() {
return this.props.todos.map((todo)=>{
return <Todo todo={todo} key={todo.id} />
})
}
render () {
return () {
if (this.props.todos.length === 0) {
return <div>No todos</div>
}
return (
<div>
{this.renderTodos()}
</div>
)
}
}
}
export default class TodoList
Todo.js
class Todo extends Component {
render () {
return (
<div>
<span>{this.props.todo.id}</span>
<span>{this.props.todo.name}</span>
</div>
)
}
}
减速机
export default function todos(state={},action) {
switch (action.type) {
case 'RECEIVE_TODOS':
return Object.assign(state,action.todos);
}
}
动作
function fetchTodos() {
return(dispatch) => {
axios.get({
//api details
})
.then((res)=>{
dispatch(receiveTodos(res.todos))
})
.catch((err)=>{
console.warn(err)
})
}
}
function receiveTodos(todos) {
return {
type: 'RECEIVE_TODOS',
todos
}
}
现在,如果您阅读了 redux 文档,您会看到操作 return 对象,那么我将如何调用我的 api 那里 return 是一个函数而不是一个对象。为此,我使用了 redux thunk,你可以阅读 here.
我给你举了一个例子,你可以在其中获取待办事项。如果您想执行其他操作,如 deleteTodo、addTodo、modifyTodo,那么您可以在适当的组件中执行这些操作。
- DeleteTodo - 您可以在 TodoListContainer 中执行。
- AddingTodo - 您可以在 TodoListContainer 中完成。
- 改变状态(completed/Pending) - 你可以在 TodoListContainer 中做。
- ModifyingTodo - 你可以在 TodoContainer 中做。
您也可以查看here for a detailed example, but before that I would say just should go through basics of redux which you can find here
P.S:我是临时写的代码,所以它可能无法正常工作,但只需稍作修改就应该可以工作。
我一直在开发 React 应用程序,并且已经到了需要 Redux 来处理它的某些方面的地步。
阅读了一堆教程后,我对如何制作我的 "smarter" 组件 "dumber" 以及如何将函数移动到我的动作和 reducer 中非常困惑。
因此,例如,应用程序的一个方面更像是待办事项列表样式。
我的一个 类 是这样开始的:
export default class ItemList extends React.Component {
constructor() {
super();
this.state = { items: [],
completed: [],
};
this.addItem = this.addItem.bind(this);
this.completeItem = this.completeItem.bind(this);
this.deleteItem = this.deleteItem.bind(this);
}
addItem(e) {
var i = this.state.items;
i.push({
text: this._inputElement.value,
paused: false,
key: Date.now()
});
this.setState({ items: i });
e.preventDefault();
this._inputElement.value = '';
this._inputElement.focus();
}
completeItem(e) {
this.deleteItem(e);
var c = this.state.completed;
c.push({
text: e.target.parentNode.parentNode.getElementsByClassName('item-name')[0].innerHTML,
paused: false,
key: Date.now()
});
this.setState({ completed: c });
}
deleteItem(e) {
var i = this.state.items;
var result = i.filter(function(obj) {
return obj.text !== e.target.parentNode.parentNode.getElementsByClassName('item-name')[0].innerHTML;
});
this.setState({ items: result });
}
// ... more irrelevant code here ...
// there's a function called createTasks that renders individual items
render() {
var listItems = this.state.items.map(this.createTasks);
return <div className="item-list">
<form className="form" onSubmit={this.addItem}>
<input ref={(a) => this._inputElement = a}
placeholder="Add new item"
autoFocus />
<button type="submit"></button>
</form>
{listItems}
</div>;
}
}
因此,如您所见,它非常注重逻辑。我已经开始通过在我的索引文件中添加一个 <Provider>
来添加 Redux,并制作了一个到目前为止相当空的基本 reducers 文件:
import { combineReducers } from 'redux';
const itemList = (state = {}, action) => {
};
// ... other irrelevant reducers
const rootReducer = combineReducers({
itemList,
// ...
});
export default rootReducer;
...我制作了一个动作文件,其中也没有太多内容。
我一直在苦苦思索:
- 我见过的大多数操作只是 return 某种 JSON 的示例,我在使用我的组件 JSON 的减速器中 return 做什么可以用吗?
- 我的组件逻辑有多少是可重用的,还是我应该忘记它?尽可能多地重用我编写的代码的最佳方法是什么?
首先你需要了解redux如何与react一起工作的全貌。
在开始之前,让我们先了解一下什么是智能组件和哑组件。
智能组件
- 你所有的代码逻辑都需要在这里处理
- 它们也被称为容器。
- 他们与商店交互(也称为状态管理)以更新您的组件。
哑组件
- 他们只是从你的容器中读取道具并渲染你的组件
- 这只是 UI 视图,不应包含任何逻辑。
- 所有 styling/html/css 都在您的哑组件中。
Here 是一篇很棒的文章,如果您仍然有疑问,可以阅读它来理解聪明和愚蠢的组件。
好的,现在让我们试着理解 redux 是如何工作的:-
- 您的智能组件(又名容器)与您的 redux 存储交互
- 你从你的容器中触发动作。
- 你的行为叫你的api
- 您的操作结果通过减速器更新商店
- 您的容器通过 mapStateToProps 函数读取商店,一旦商店中的值发生变化,它就会更新您的组件。
现在让我们考虑一下您的待办事项示例
TodoListContainer.js
class TodoListContainer extends Component {
componentWillMount () {
// fire you action action
}
render () {
return (
<Todos todos=={this.props.todos} />
)
}
}
function mapStateToProps(state) {
const {todos} = state;
return {
todos;
}
}
export default connect(mapStateToProps)(TodoListContainer)
TodoList.js
class TodoList extends Component {
renderTodos() {
return this.props.todos.map((todo)=>{
return <Todo todo={todo} key={todo.id} />
})
}
render () {
return () {
if (this.props.todos.length === 0) {
return <div>No todos</div>
}
return (
<div>
{this.renderTodos()}
</div>
)
}
}
}
export default class TodoList
Todo.js
class Todo extends Component {
render () {
return (
<div>
<span>{this.props.todo.id}</span>
<span>{this.props.todo.name}</span>
</div>
)
}
}
减速机
export default function todos(state={},action) {
switch (action.type) {
case 'RECEIVE_TODOS':
return Object.assign(state,action.todos);
}
}
动作
function fetchTodos() {
return(dispatch) => {
axios.get({
//api details
})
.then((res)=>{
dispatch(receiveTodos(res.todos))
})
.catch((err)=>{
console.warn(err)
})
}
}
function receiveTodos(todos) {
return {
type: 'RECEIVE_TODOS',
todos
}
}
现在,如果您阅读了 redux 文档,您会看到操作 return 对象,那么我将如何调用我的 api 那里 return 是一个函数而不是一个对象。为此,我使用了 redux thunk,你可以阅读 here.
我给你举了一个例子,你可以在其中获取待办事项。如果您想执行其他操作,如 deleteTodo、addTodo、modifyTodo,那么您可以在适当的组件中执行这些操作。
- DeleteTodo - 您可以在 TodoListContainer 中执行。
- AddingTodo - 您可以在 TodoListContainer 中完成。
- 改变状态(completed/Pending) - 你可以在 TodoListContainer 中做。
- ModifyingTodo - 你可以在 TodoContainer 中做。
您也可以查看here for a detailed example, but before that I would say just should go through basics of redux which you can find here
P.S:我是临时写的代码,所以它可能无法正常工作,但只需稍作修改就应该可以工作。