将Redux添加到现有的React应用程序

时间:2017-04-13 00:19:31

标签: reactjs redux react-redux

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

在阅读了一堆教程之后,我完全坚持如何让我的“更聪明”的组件“笨拙”并将功能转移到我的行动和减速器中。

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

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

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;

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

我一直在努力弄明白:

  • 我见过的大多数动作只返回某种JSON,我在使用我的组件可以使用的JSON的reducer中返回什么?
  • 我的组件逻辑有多少是可重用的,或者我应该忘记它?什么是最好的方法来重用尽可能多的代码?

1 个答案:

答案 0 :(得分:24)

首先,您需要了解redux如何使用react的整体情况。

在开始之前,首先要了解什么是智能组件和哑组件。

智能组件

  1. 您需要在此处理所有代码逻辑
  2. 它们也被称为容器。
  3. 他们与商店(又名州管理层)互动以更新您的组件。
  4. 哑组件

    1. 他们只是从容器中读取道具并渲染组件
    2. 这只是UI视图,不应包含任何逻辑。
    3. 所有样式/ html / css都会出现在您的愚蠢组件中。
    4. Here是一篇非常精彩的文章,如果你仍然有疑问,你可以通过它来理解聪明和愚蠢的组件。

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

      • 您的智能组件(也称为容器)与您的redux商店互动
      • 您从容器中触发操作。
      • 你的行动叫你的apis
      • 您的操作结果通过reducer更新商店
      • 您的容器通过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文档,您会看到操作返回对象,那么我将如何调用我的api,返回函数而不是对象。为此,我使用了redux thunk,你可以阅读here

      我举了一个例子,你可以拿到待办事项。如果你想做其他操作,比如deleteTodo,addTodo,modifyTodo那么你可以在适当的组件中做到这一点。

      1. DeleteTodo - 您可以使用TodoListContainer。
      2. AddingTodo - 你可以在TodoListContainer。
      3. 更改状态(已完成/待定) - 您可以使用TodoListContainer。
      4. ModifyingTodo - 您可以在TodoContainer中完成。
      5. 您还可以查看here以获取详细示例,但在此之前我会说应该通过您可以找到的redux的基础知识here

        P.S:我在运行中编写了代码,因此它可能无法正常工作,但它应该稍作修改。