将 Redux 添加到现有的 React 应用程序 [英] Adding Redux to an existing React app

查看:38
本文介绍了将 Redux 添加到现有的 React 应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在开发 React 应用程序,并且已经到了需要 Redux 来处理它的某些方面的地步.

在阅读了大量教程后,我对如何使我的更智能"组件变得笨拙"并将函数移动到我的操作和减速器中相当困难.

因此,例如,应用程序的一个方面更像是待办事项列表样式.

我的一个课程是这样开始的:

export default class ItemList extends React.Component {构造函数(){极好的();this.state = { 项目:[],完全的: [],};this.addItem = this.addItem.bind(this);this.completeItem = this.completeItem.bind(this);this.deleteItem = this.deleteItem.bind(this);}添加项目(e){var i = this.state.items;i.push({文本:this._inputElement.value,暂停:假,关键:Date.now()});this.setState({ items: i });e.preventDefault();this._inputElement.value = '';this._inputElement.focus();}完成项目(e){this.deleteItem(e);var c = this.state.completed;c.推({文本:e.target.parentNode.parentNode.getElementsByClassName('item-name')[0].innerHTML,暂停:假,关键:Date.now()});this.setState({ 完成: c });}删除项目(e){var i = this.state.items;var 结果 = i.filter(function(obj) {return obj.text !== e.target.parentNode.parentNode.getElementsByClassName('item-name')[0].innerHTML;});this.setState({ items: result });}//... 这里有更多不相关的代码 ...//有一个名为 createTasks 的函数,用于呈现单个项目使成为() {var listItems = this.state.items.map(this.createTasks);return 

<form className="form" onSubmit={this.addItem}><输入参考={(a)=>this._inputElement = a}placeholder="添加新项目"自动对焦/><button type="submit"></button></表单>{列表项}

;}}

所以,正如您所看到的,它的逻辑非常繁重.我已经通过在我的索引文件中添加一个 <Provider> 开始添加 Redux,并制作了一个到目前为止相当空的基本 reducers 文件:

import { combineReducers } from 'redux';const itemList = (state = {}, action) =>{};//... 其他不相关的减速器const rootReducer = combineReducers({项目列表,//...});导出默认的 rootReducer;

...而且我已经制作了一个动作文件,其中也没有太多内容.

我一直在努力弄清楚:

  • 我见过的大多数操作示例都只返回某种 JSON,我在使用组件可以使用的 JSON 的 reducer 中返回什么?
  • 我的组件逻辑有多少是可重用的,还是我应该忘记它?要重用我编写的尽可能多的代码,最好的方法是什么?

解决方案

首先你需要了解 redux 如何与 react 协同工作的整体图.

在开始之前,让我们先了解什么是智能组件和哑组件.

智能组件

  1. 你所有的代码逻辑都需要在这里处理
  2. 它们也称为容器.
  3. 他们与商店(又名状态管理)交互以更新您的组件.

哑组件

  1. 他们只是从你的容器中读取 props 并渲染你的组件
  2. 这只是 UI 视图,不应包含任何逻辑.
  3. 所有样式/html/css 都包含在您的愚蠢组件中.

这里是一篇很棒的文章,你可以去看看如果您仍有疑问,请通过了解智能和愚蠢的组件.

好的,现在让我们尝试了解 redux 的工作原理:-

  • 您的智能组件(又名容器)与您的 redux 存储交互
  • 您从容器中触发操作.
  • 你的行为调用你的 API
  • 您的操作结果通过减速器更新商店
  • 您的容器通过 mapStateToProps 函数读取存储,一旦存储中的值发生变化,它就会更新您的组件.

现在让我们考虑您的待办事项示例

TodoListContainer.js

class TodoListContainer 扩展组件 {组件WillMount(){//激发你的动作动作}使成为 () {返回 (<Todos todos=={this.props.todos}/>)}}函数 mapStateToProps(state) {const {todos} = 状态;返回 {待办事项;}}导出默认连接(mapStateToProps)(TodoListContainer)

TodoList.js

class TodoList 扩展组件 {renderTodos() {返回 this.props.todos.map((todo)=>{return })}使成为 () {返回 () {如果(this.props.todos.length === 0){return <div>没有待办事项</div>}返回 (<div>{this.renderTodos()}

)}}}导出默认类 TodoList

Todo.js

class Todo extends Component {使成为 () {返回 (<div><span>{this.props.todo.id}</span><span>{this.props.todo.name}</span>

)}}

减速器

导出默认函数 todos(state={},action) {开关(动作.类型){案例'RECEIVE_TODOS':返回 Object.assign(state,action.todos);}}

行动

function fetchTodos() {返回(调度)=>{axios.get({//api详细信息}).then((res)=>{调度(接收Todos(res.todos))}).catch((错误)=>{控制台警告(错误)})}}功能接收Todos(todos){返回 {类型:'RECEIVE_TODOS',待办事项}}

现在,如果您已阅读 redux 文档,您会看到操作返回对象,那么我将如何在那里调用我的 api,它返回一个函数而不是一个对象.为此,我使用了 redux thunk,你可以在这里阅读.

我给了你一个例子,你可以在其中获取待办事项.如果你想做其他的操作,比如 deleteTodo、addTodo、modifyTodo,那么你可以在适当的组件中进行.

  1. DeleteTodo - 您可以在 TodoListContainer 中进行.
  2. AddingTodo - 你可以在 TodoListContainer 中做.
  3. 更改状态(已完成/待处理) - 您可以在 TodoListContainer 中进行.
  4. ModifyingTodo - 您可以在 TodoContainer 中进行.

您还可以查看此处以获得详细示例,但是在此之前,我想说的是应该了解 redux 的基础知识,您可以在 here

P.S:我即时编写了代码,因此它可能无法正常工作,但只需稍加修改即可工作.

I've been working on a React app and have gotten to a point where I'll need Redux to handle some aspects of it.

After reading a bunch of tutorials, I'm fairly stuck on how to make my "smarter" components "dumber" and move functions into my actions and reducers.

So, for example, one aspect of the app is more of a to-do list style.

One of my classes starts like this:

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>;
  }
}

So, as you can see, it's very logic-heavy. I've started adding Redux by adding a <Provider> in my index file, and made a basic reducers file that is fairly empty so far:

import { combineReducers } from 'redux';

const itemList = (state = {}, action) => {

};

// ... other irrelevant reducers

const rootReducer = combineReducers({
  itemList,
  // ...
});

export default rootReducer;

...and I've made an actions file that doesn't have much in it yet either.

I've been struggling to figure out:

  • Most actions I've seen examples of just return some kind of JSON, what do I return in the reducer that uses that JSON that my component can use?
  • How much of my component logic is reusable, or should I just forget it? What is the best way to go about this to reuse as much code as I've written as possible?

解决方案

First of all you need to understand the overall picture of how redux works with react.

Before coming to that lets first understand what are smart components and dumb components.

Smart Components

  1. All your code logic needs to be handled here
  2. They are also called containers.
  3. They interact with the store(aka state management) to update your components.

Dumb Components

  1. They just read props from your containers and render you components
  2. This is just the UI view and should not contain any logic.
  3. All styling/html/css comes in your dumb components.

Here is an amazing piece of article which you can go through to understand smart and dumb components if you still have doubts.

Ok, now lets try understanding how redux works:-

  • Your smart components(aka containers) interact with your redux store
  • You fire actions from your containers.
  • Your actions call your apis
  • The result of your action updates the store through a reducer
  • You containers read the store through mapStateToProps function and as soon as value in store changes it updates your component.

Now lets consider your todo example

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>
    )
  }
}

Reducer

export default function todos(state={},action) {
  switch (action.type) {
    case 'RECEIVE_TODOS':
       return Object.assign(state,action.todos);
  }
}

action

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
  }
}

Now if you have read redux documentation you would see that actions return objects then how would i call my api there which returns a function instead of an object. For that I used redux thunk about which you can read here.

I gave you an example in which you can fetch todos. If you want to do other operations like deleteTodo, addTodo, modifyTodo then you can do that in appropriate components.

  1. DeleteTodo - you can do in TodoListContainer.
  2. AddingTodo - you can do in TodoListContainer.
  3. Changing State(completed/Pending) - you can do in TodoListContainer.
  4. ModifyingTodo - you can do in TodoContainer.

You can also check out 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: I wrote code on the fly so it might not work properly but it should work with little modification.

这篇关于将 Redux 添加到现有的 React 应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆