【问题标题】:Adding Redux to an existing React app将 Redux 添加到现有的 React 应用程序
【发布时间】:2017-04-13 00:19:31
【问题描述】:

我一直在开发一个 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>;
  }
}

所以,如您所见,它非常注重逻辑。我已经开始通过在我的索引文件中添加 &lt;Provider&gt; 来添加 Redux,并制作了一个到目前为止相当空的基本 reducers 文件:

import { combineReducers } from 'redux';

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

};

// ... other irrelevant reducers

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

export default rootReducer;

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

我一直在努力弄清楚:

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

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    首先你需要了解 redux 如何与 react 协同工作的整体情况。

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

    智能组件

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

    哑组件

    1. 他们只是从您的容器中读取道具并为您呈现组件
    2. 这只是 UI 视图,不应包含任何逻辑。
    3. 所有样式/html/css 都包含在您的哑组件中。

    Here 是一篇了不起的文章,如果您仍有疑问,可以阅读它来了解智能组件和愚蠢组件。

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

    • 您的智能组件(也称为容器)与您的 redux 存储交互
    • 您从容器中触发操作。
    • 您的操作调用您的 API
    • 您的操作结果通过 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 中进行。

    您也可以查看here 以获取详细示例,但在此之前我会说应该先了解一下您可以找到here 的redux 基础知识

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

    【讨论】:

    • 请考虑添加不再推荐这种方法的免责声明(参考您引用的帖子)
    猜你喜欢
    • 2018-07-21
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2017-06-12
    相关资源
    最近更新 更多