美文网首页让前端飞Web前端之路React.js
我理解的todos(redux+react-redux)

我理解的todos(redux+react-redux)

作者: 换昵称了 | 来源:发表于2019-01-17 10:35 被阅读5次

    demo地址:

    git clone https://github.com/reactjs/redux.git
    cd redux/examples/todos
    npm install
    npm start
    

    3.第一部分(如图)

    addTodo.png
    1.入口文件index.js
    import React from 'react'
    import { render } from 'react-dom'
    import { createStore } from 'redux'
    import { Provider } from 'react-redux'
    import App from './components/App'
    import rootReducer from './reducers'
    
    const store = createStore(rootReducer)
    render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById('root')
    )
    
    

    Provider作用:将store传给组件,与connect配合使用,connect则是将组件与redux关联起来。本质上 Provider 就是给 connect 提供 store 用的。(react-redux提供)

    2.组件入口App.js
    import React from 'react';
    import AddTodo from '../containers/AddTodo'
    import VisibleTodoList from '../containers/VisibleTodoList'
    // 使用jsx写法一定要引入react,不然会报错:'React' must be in scope when using JSX  react/react-in-jsx-scope
    const App = () => {
        return (
            <div>
                <AddTodo />
                <VisibleTodoList />
            </div>
        )
    }
    
    export default App;
    
    3.AddTodo 的action以及reducer
    //action.js   
    let nextTodoId = 0;
    export const addTodo = (text) => {
        return {
            type: 'ADD_TODO',
            //id存在的意义是作为key
            id: nextTodoId++,
            text
        }
    }
    //reducer
    const todos = (state = [], action) => {
        switch (action.type) {
            case 'ADD_TODO':
                return [
                    ...state,
                    {
                        id: action.id,
                        text: action.text,
                        completed: false
                    }
                ]
            default:
                return state
        }
    }
    
    export default todos
    

    上面我们已经将reducer作为参数传入了store,所以只要触发dipatch,就会根据type做出相应的更新。
    ...state解构写法,一定要给state一个默认值,不然会报错。

    4.组件AddTodo.js
    import React from 'react'
    import { addTodo } from '../actions'
    import { connect } from 'react-redux'
    //{dispatch}解构写法,也可以写成任意一个变量名,比如a,获取dipatch:a.dipatch
    const AddTodo = ({ dispatch }) => {
        let input;
        return (
            <form action="" onSubmit={
                (e) => {
                    e.preventDefault() //阻止默认事件,比如这里点击按钮会刷新页面
                    dispatch(addTodo(input.value))
                    input.value = ''
                }
            }>
                <input type="text" ref={node => { input = node }} />
                <button type="submit">
                    addTodo
                </button>
            </form>
        )
    }
    
    export default connect()(AddTodo)
    

    action和reducer之间能联系起来的关键是connect,connect将store和组件联系起来,即connect连接视图和数据层。通过provider把store绑定在组件上(provider为connect提供了store),当dispatch 的时候,会更新相对应type的store数据 。(有点乱,对于connect的具体解析可参考https://www.jianshu.com/p/9873d4ccb891(关于react-redux中的connect用法介绍及原理解析))

    5.VisibleTodoList.js
    import { connect } from 'react-redux'
    import TodoList from '../components/TodoList'
    
    const getVisibleTodos = (todos) => {
        console.log(todos)
        return todos
    }
    const mapStateToProps = state => ({
        todos: getVisibleTodos(state.todos)
    })
    
    export default connect(
        mapStateToProps
    )(TodoList)
    

    connect的个人总结:

    • connect 连接组件和store
    • connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])
    • mapStateToProps: mapStateToProps(state,ownProps):stateProps,将store中的数据作为props绑定到组件上
    • mapDispatchToProps(dipatch,ownProps):dispatchProps,将action作为props绑定到组件上

    第二部分(如图)

    todoList.png
    1.actions 和reducers
    //actions
    export const VisibilityFilters = {
        SHOW_ALL: 'SHOW_ALL',
        SHOW_COMPLETED: 'SHOW_COMLETED',
        SHOW_ACTIVE: 'SHOW_ACTIVE'
    }
    
    export const toggleTodo = (id) => (
        {
            type: 'TOGGLE_TODO',
            id
        }
    )
    

    VisibilityFilters是用来判断三种列表显示状态。SHOW_ALL显示全部,SHOW_COMPLETED显示已完成的,SHOW_ACTIVE显示正在进行的

    //reducers
    const todos = (state = [], action) => {
      switch (action.type) {
        case 'ADD_TODO':
          return [
            ...state,
            {
              id: action.id,
              text: action.text,
              completed: false
            }
          ]
        case 'TOGGLE_TODO':
          return state.map(todo =>
            (todo.id === action.id)
              ? {...todo, completed: !todo.completed}
              : todo
          )
        default:
          return state
      }
    }
    
    export default todos
    
    2.组件

    TodoList.js

    import React from 'react'
    import Todo from './Todo'
    
    const TodoList = ({ todos, toggleTodo }) => (
      <ul>
        {todos.map(todo =>
          <Todo
            key={todo.id}
            {...todo}
            onClick={() => toggleTodo(todo.id)}
          />
        )}
      </ul>
    )
    
    export default TodoList
    

    Todo.js

    import React from 'react'
    const Todo = ({ onClick, completed, text }) => (
        <li
            onClick={onClick}
            style={{
                textDecoration: completed ? 'line-through' : 'none'
            }}
        >
            {text}
        </li>
    )
    
    export default Todo
    
    这部分的重点
    import { connect } from 'react-redux'
    import { toggleTodo, VisibilityFilters } from '../actions'
    import TodoList from '../components/TodoList'
    
    const getVisibleTodos = (todos, filter) => {
        switch (filter) {
            case VisibilityFilters.SHOW_ALL:
                return todos
            case VisibilityFilters.SHOW_COMPLETED:
                return todos.filter(t => t.completed)
            case VisibilityFilters.SHOW_ACTIVE:
                return todos.filter(t => !t.completed)
            default:
                throw new Error('Unknown filter: ' + filter)
        }
    }
    
    const mapStateToProps = state => ({
        todos: getVisibleTodos(state.todos, state.visibilityFilter)
    })
    
    const mapDispatchToProps = dispatch => ({
        toggleTodo: id => dispatch(toggleTodo(id))
    })
    
    export default connect(
        mapStateToProps,
        mapDispatchToProps
    )(TodoList)
    

    我的理解:
    通过connect把组件与store建立起联系。
    传入的第一个参数mapStateToProps,我们将store中的数据作为props绑定到组件中,所以这里我们能拿得到state。
    传入的第二个参数mapDispatchToProps,参数是dispatch,则是我们将action作为props绑定到组件中,所以当我们点击todoList 的时候,就会触发dispatch,返回包含对应action的object对象。
    回到todoList:todoList的两个参数{todos,toggleTodo}就是这样获取的。通过解构在Todo中拿到了action对应的两个参数{completed,text}

    相关文章

      网友评论

        本文标题:我理解的todos(redux+react-redux)

        本文链接:https://www.haomeiwen.com/subject/bqtjfftx.html