首页 文章

Redux如何在React中更改UI?

提问于
浏览
5

我一直在努力围绕这个概念,但没有运气 . 官方的React教程非常好,但对我来说这太复杂了,只是有点太难了 .

我正在尝试理解Redux,到目前为止,我可以创建动作,减少器,我可以调度一个动作,然后在调度后查看存储状态如何变化 . 我还设法理解了react-redux的 connect 并且它工作得很好而且我在房间里的大象 - 我发送动作,我看到Redux状态改变但是我如何更改UI?

例如,我的初始状态为 text 对象,其值为 Initial text ,单击一个按钮后,我想将文本更改为 Clicked text 并在UI中的某处显示文本(比如说按钮) .

如何在React中“访问”Redux状态,如何动态更改它?

没有React似乎很简单,例如..:https://jsfiddle.net/loktar/v1kvcjbu/ - render 函数处理一切,我理解这里发生的一切 .

但另一方面,来自官方React Redux教程的"todo"看起来像这样:https://redux.js.org/docs/basics/ExampleTodoList.html,它太复杂了我不知道在哪里看 .

Add Todo 按钮提交一个调度 dispatch(addTodo(input.value)) 动作的表单 . 动作本身不会增加ID并将文本传递给存储,而reducer只返回新状态 . 然后如何在页面上呈现待办事项?哪里?我喜欢有一个按钮Redux教程,它仍然可以复杂多层组件:(

我怀疑魔法发生在TodoList.js中,因为他们正在那里映射,但我仍然不知道todos来自哪里,以及它与Redux有什么关系(该文件中没有简单的reducer / action / dispatch) .

谢谢你的帮助!

2 回答

  • 1

    我认为你的困惑是reducer compositionselectors的一部分 .

    让我们从UI背面以相反的顺序查看它 .

    In the connected component containers/VisibleTodoList.js它从 mapStateToPropsredux 的全局存储对象) mapStateToProps 中获取 todos ,同时通过 getVisibleTodos 方法传递它 .
    这可以称为选择器,因为它只选择并返回它接收的部分数据:

    import { connect } from 'react-redux'
    import { toggleTodo } from '../actions'
    import TodoList from '../components/TodoList'
    
    const getVisibleTodos = (todos, filter) => {
      switch (filter) {
        case 'SHOW_COMPLETED':
          return todos.filter(t => t.completed)
        case 'SHOW_ACTIVE':
          return todos.filter(t => !t.completed)
        case 'SHOW_ALL':
        default:
          return todos
      }
    }
    
    const mapStateToProps = state => {
      return {
        todos: getVisibleTodos(state.todos, state.visibilityFilter)
      }
    }
    
    const mapDispatchToProps = dispatch => {
      return {
        onTodoClick: id => {
          dispatch(toggleTodo(id))
        }
      }
    }
    
    const VisibleTodoList = connect(
      mapStateToProps,
      mapDispatchToProps
    )(TodoList)
    
    export default VisibleTodoList
    

    传递给 mapStateToPropsThe state (redux store) 来自根减速器reducers/index.js,实际上是一个减速器(对象),它通过 reduxcombineReducers 实用程序表示所有其他减速器的组合:

    import { combineReducers } from 'redux'
      import todos from './todos'
      import visibilityFilter from './visibilityFilter'
    
      const todoApp = combineReducers({
        todos,
        visibilityFilter
      })
    
      export default todoApp
    

    如您所见, todos 减速器就在那里 . 所以这就是为什么在 mapStateToProps 里面我们称之为 state.todos .

    这是reducers/todos.js

    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
    

    'ADD_TODO' 类型的每个操作上,它将返回一个具有新 todo 的新状态:

    case 'ADD_TODO':
              return [
                ...state,
                {
                  id: action.id,
                  text: action.text,
                  completed: false
                }
              ]
    

    这是actions/index.js内的动作创建者:

    let nextTodoId = 0
    export const addTodo = text => {
      return {
        type: 'ADD_TODO',
        id: nextTodoId++,
        text
      }
    }
    

    所以这里是 redux 的完整流程(我省略了调用动作的按钮,因为我认为这对你来说很明显) .
    好吧,几乎是一个完整的流程,如果没有 Provider HOC包裹 App 并在index.js注入商店,这一切都不会发生:

    import React from 'react'
    import { render } from 'react-dom'
    import { Provider } from 'react-redux'
    import { createStore } from 'redux'
    import todoApp from './reducers'
    import App from './components/App'
    
    let store = createStore(todoApp)
    
    render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('root')
    )
    

    现在当 redux state 更改时,将调用 mapStateToProps 调用,该调用将返回新映射的 props . connect 将传递那些新的 props ,这将触发一个新的 render 调用(实际上是整个反应生命周期流程)到连接的组件 .
    这样,UI将使用来自商店的新数据重新呈现 .

  • 5

    connect通常用于连接react组件和Redux state.connect是一个更高阶的组件 . 使用connect功能的组件包含在其中 . 方法签名是connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])mapStateToProps可以访问redux状态,mapDispathToProps可以访问store.dispatch . 所有道具都合并并作为道具传递给底层组件 . Redux只有单一的真实状态 . 作为props传递给Provider组件的商店有一个名为store.getState()的方法 .

    因此,请记住一件事,反应组件是数据驱动的 . 数据派生UI . 仅当状态更改或道具已被修改时,React组件才会重新呈现 . 您可以在两个组件中进行更改,组件会经历各种生命周期方法 .

相关问题