带有REDUX的国家管理
#javascript #网络开发人员 #react #redux

介绍

状态管理非常必要,因为它有助于使数据在应用程序的任何部分都可以访问而无需重复向服务器查询相同的数据,而状态管理可以查询数据并将其存储在应用程序中的特定部分中然后从商店获取数据。

对于本文,您将使用Redux(Redux-Toolkit)作为状态管理工具。

了解Redux

redux(Redux Toolkit)是现代JavaScript UI框架(例如React,Vue和Angular)中使用的流行状态管理工具之一,在所有其他状态管理工具中,都更容易存储数据,并且还可以检索您将要检索的数据请参阅一分钟之内,有关更多了解,您可以访问Redux网站,以便对Redux使用的方法以及有关Redux(Redux Toolkit)的任何其他详细信息(Redux Toolkit)的前瞻性说明,此外,对于此特定项目,我们将使用React.js来了解React.js如何使用redux(redux工具包)。

什么是反应

react.js是由Facebook构建的JavaScript UI框架,由Facebook开发人员管理,它的开发是为了帮助将Web UI的某些部分分为较小的组件,从而使这些组件可重复使用,并且许多其他很棒的组件我也建议您检查他们的official website是否有更多令人敬畏的reactjs以及如何使用它们。

为什么要redux

关于Redux(Redux Toolkit)的一件很棒的事情是,它使您可以将存储数据分为不同的文件,并使用Combinereducers()方法将它们组合在一起,并且还使将数据从一个组件传递到另一个组件到另一个组件更轻松而无缝,而不是从一个父母到子女到子女,而在大型项目中工作可能会令人困惑,而是您存储

(调度)商店中的数据并将其从商店中检索到您要使用的任何组件中。

先决条件

在此过程中拥有此过程的重要工具是Node.js,现在您应该在计算机上安装Node >= 14.0.0 and npm >= 5.6,如果您不需要您现在下载click here即可下载。

以及对ES6

的基本理解

现在,如果您已经有一个ReactJS项目,请继续进行,您可以跳到在React Project中安装Redux ,如果您没有设置ReactJS项目,已经已经设置了到下一个。

建立一个新的react.js项目

在设置ReactJS项目时,我们将使用Create-React-App,为此,您必须打开命令行(命令提示符)和键入。

npx create-react-app my-app-name

这样,您已经成功创建了一个新的React应用程序,直到下一个

在React项目中安装Redux

如果您刚刚与我们一起安装了一个新的React应用程序,仍然可以在您的终端上进行导航到新项目

cd my-app-name 

,如果已经有一个项目,则可以在终端上打开项目,

现在,我们都在终端上的项目中,是时候在我们的React项目上安装Redux了,为此,我们将键入

npm安装react-redux

完成此操作,我们现在在应用程序中安装了Redux

npm install react-redux

现在,我们已经完成并安装它以运行我们的应用程序,并在终端类型上执行此操作

npm start

设置Redux商店

为了学习目的,我们将构建一个简单的待办事项应用程序,该应用程序将帮助我们理解使用Redux Store的基本概念。

我们将为TODO App

设置我们的商店

在SRC文件夹中执行此操作是创建一个名为“商店”的文件夹的最佳实践,这是所有数据都将存储的地方,只是为了拥有一个良好且整洁的工作流程。在您的商店文件夹中创建一个文件,它可以称为您选择的任何东西,但是为此,我们将其称为index.js。

现在在您的index.js文件中,首先您必须从redux库中导入stestestore方法

以及导出stestestore商店,您只需复制以下并将其粘贴到索引中。JS文件

import {createStore} from 'redux'

export const store = createStore()

现在,stestestore方法接受两个参数,第一个是您想要使用的reducer,第二个是reducer的初始状态,它通常不经常是nessceary,因为它也可以使用reducer传递,这是我们的方法,这是我们的方法。将用于为我们的待办事项设置一个简化器,因此我们必须更新我们在商店中创建的index.js文件

您只需复制下面的代码

import {createStore} from 'redux'
const INITIAL_STATE = {
    todos : []
};
const reducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case "ADD_TODO":
            return {
                ...state,
                todos : [...state.todos,action.payload]
            };
        case "COMPLETED_TODO":
            return {
                ...state,

            };
        case "REMOVE_TODO":
            return {
                ...state,

            };
        default:
            return state;
    }
};
export const store = createStore(reducer)

,如果您不了解还原钩的工作原理,我建议您检查react.js official docs以了解其工作原理。

此还原器只需添加,更新和删除商店中的项目。

我们尚未完成您的main.jsx或index.js文件中的最后一件事

您可以复制下面的代码

import { Provider } from 'react-redux';
import { store } from './Store/index';

导入后,您必须将导出的应用程序组件与提供商包装,然后在提供商中,它具有称为商店的属性,然后将导入的商店传递到其中。

您可以复制下面的代码

<Provider store={store}>
    <App />
</Provider>

现在,我们已经完成了设置商店并连接到商店,让我们构建一个简单的待办事项UI,因为您不必担心,因为我只会在这里粘贴所有代码,但是如果您已经有一个设计或您可以跳过将Redux集成到您的React组件中

import {  useState } from 'react';
import './App.css';
function App() {
  const [todo,setTodo] = useState('');
  const submit = (e) => {
    e.preventDefault();
    console.log(todo);
    setTodo('')
  }
  return (
    <div className="App">
      <div className="body">
        <form onSubmit={submit} style={{ 'padding': '0px 0px 12px 0px', }}>
          <input required 
                                 value={todo} 
                                 onChange={(e)=> setTodo(e.target.value)} 
                                 type="text" 
                                 placeholder='Enter TODO task'/>
          <button type='submit'>ADD TODO</button>
        </form>
        <div>
          <div style={{ 'padding': '0px 0px 12px 0px', }}>TODO's</div>
        </div>
      </div>
    </div>
  );
}

export default App;

和您的app.css

.body{
  margin: 0px auto;
  max-width: 800px;
  padding: 10px;
}
.todoCard{
  position: relative;
  border: 1px solid gray;
  margin-top: 7px;
  padding: 4px;
  border-radius: 9px;
  margin: 0px auto;
  max-width: 800px;
}

.wrapper{
  display: flex;
  width: 100%;
}
.todoText{
  flex-grow: 1;
  font-size: small;
}
.doneBtn{
  font-size: 12px;
  padding: 5px 12px;
  border-radius: 9px;
  text-transform: uppercase;
}
.btn-color1{
  background-color: #1a7719;
  color: aliceblue;
  cursor: pointer;
}
.btn-color2{
  background-color: #b0b3b0;
  pointer-events: none;
}

之后,您的UI应该喜欢

Image description

如果有的话,那意味着我们很高兴,是时候将我们的组件连接到商店访问数据了。

将Redux集成到您的React组件中

首先在要访问必须从react-redux导入的数据的组件上,它应该像这样。

import { connect } from 'react-redux'

导入此之后,您必须与文件名一起导出连接,而文件名是我们的情况,您必须重写导出才能看起来像

export default connect()(App)

在此过程结束时,您的组件应看起来像下面的片段。

import {  useEffect, useState } from 'react';
import React from 'react'
import { connect } from 'react-redux'
import './App.css';
function App() {
  const [todo,setTodo] = useState('');
  const submit = (e) => {
    e.preventDefault();
    setTodo('')
  }
  useEffect(() => {

  }, [])

  return (
    <div className="App">
      <div className="body">
        <form onSubmit={submit} style={{ 'padding': '0px 0px 12px 0px', }}>
          <input required 
                                 value={todo} 
                                 onChange={(e)=> setTodo(e.target.value)} 
                                 type="text" 
                                 placeholder='Enter TODO task'/>
          <button type='submit'>ADD TODO</button>
        </form>
        <div>
          <div style={{ 'padding': '0px 0px 12px 0px', }}>TODO's</div>
        </div>
      </div>
    </div>
  );
}
export default connect()(App)

如果您已经完成了此操作,那么您已经成功地将您的组件连接到了商店,

现在是时候将数据派遣到Redux商店了。

在商店中派遣数据

在将数据发送到商店时,在导出的连接方法中,我们可以通过称为 mapdispatchtoprops 的函数,此名称完全取决于您,您可以将其称为您想要的任何内容我们给函数的名称,然后将其传递到连接方法中。

此功能依次返回商店中可以执行的所有操作,该操作现在将添加到商店中。

注意:您的调度类型必须与Reducer Store中的分类类型相同

和有效载荷包含要存储的实际数据

我认为代码片段会更多地解释。

const mapDispatchToProps = (dispatch) =>{
  return{
      addTodo: (todo) => {
        dispatch({type:"ADD_TODO" , payload : { todo ,status:false}})
      }
  }
}

export default connect(mapDispatchToProps)(App)
  • 功能组件

    并访问UI中的操作或在我们的情况下,我们在功能组件中的提交功能,您必须首先将道具传递到功能中,因为它可以从道具中访问dispatch诉讼。

    和创建的提交函数中,您可以使用addtodo操作,然后将todo从输入传递给它。有了下面的代码,您可以了解更多。

    import {  useEffect, useState } from 'react';
    import React from 'react'
    import { connect } from 'react-redux'
    import './App.css';
    function App(props) {
      const [todo,setTodo] = useState('');
      const submit = (e) => {
        e.preventDefault();
        props.addTodo(todo)
        setTodo('')
      }
      useEffect(() => {
    
      }, [])
    
      return (
        <div className="App">
          <div className="body">
            <form onSubmit={submit} style={{ 'padding': '0px 0px 12px 0px', }}>
              <input required 
                                     value={todo} 
                                     onChange={(e)=> setTodo(e.target.value)} 
                                     type="text" 
                                     placeholder='Enter TODO task'/>
              <button type='submit'>ADD TODO</button>
            </form>
            <div>
              <div style={{ 'padding': '0px 0px 12px 0px', }}>TODO's</div>
            </div>
          </div>
        </div>
      );
    }
    
    const mapDispatchToProps = (dispatch) =>{
      return{
          addTodo: (todo) => {
            dispatch({type:"ADD_TODO" , payload : { todo ,status:false}})
          }
      }
    }
    
    export default connect(mapDispatchToProps)(App)
    
  • 类组件

    要访问道具,您必须添加它,并且您不必通过组件将道具通过以下输出。

    import React, { Component } from 'react'
    import { connect } from 'react-redux'
    import './App.css';
    
    export class App extends Component {
      constructor(props) {
        super(props)
        this.state = {
          todo : '',
        }
      }
      submit(e){
        e.preventDefault();
        this.props.addTodo(this.state.todo)
        this.setState({todo : ''})
      }
      render() {
        return (
          <div className="App">
            <div className="body">
              <form onSubmit={e => this.submit(e)}
                                  style={{ 'padding': '0px 0px 12px 0px', }}>
                <input required 
                                         value={this.state.todo} 
                                         onChange={(e)=> this.setState({todo : e.target.value})}
                                         type="text"
                                         placeholder='Enter TODO task'/>
                <button type='submit'>ADD TODO</button>
              </form>
              <div>
                <div style={{ 'padding': '0px 0px 12px 0px', }}>TODO's</div>
              </div>
            </div>
          </div>
        )
      }
    }
    
    const mapDispatchToProps = (dispatch) =>{
      return{
          addTodo: (todo) => {
            dispatch({type:"ADD_TODO" , payload : { todo ,status:false}})
          }
      }
    }
    
    export default connect(mapDispatchToProps)(App)
    

从商店访问数据

现在,我们已成功将数据派遣到商店中,我们必须检索存储的数据

连接方法还可以接受另一个函数作为参数将所有数据保存在商店中的状态依次可以访问该州中的这些数据并将它们分配给我们可以在UI中访问它们的密钥

下面的代码片段应该对其进行更多解释。

const mapStateToProps = (state) => ({
  list : state.todos
})

const mapDispatchToProps = (dispatch) =>{
  return{
      addTodo: (todo) => {
        dispatch({type:"ADD_TODO" , payload : { todo ,status:false}})
      }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App)

现在这是您的代码。

现在我们已经在商店中获得了数据,我们必须显示它们,因此我们将更新UI

  • 功能组件

    如果您使用功能组件访问列表数据,则可以复制下面的代码。

    return (
        <div className="App">
          <div className="body">
            <form onSubmit={submit} style={{ 'padding': '0px 0px 12px 0px', }}>
                  <input required
                                         value={todo} 
                                         onChange={(e)=> setTodo(e.target.value)} 
                                         type="text" placeholder='Enter TODO task'/>
              <button type='submit'>ADD TODO</button>
            </form>
            <div>
              <div style={{ 'padding': '0px 0px 12px 0px', }}>TODO's</div>
              {
                          props.list.map((todo,i) => (
                            <div className="todoCard" 
                                             key={i} style={{'margin':'8px 0px 0px 0px'}}>
                              <div className="wrapper">
                                <div className="todoText">{todo.todo}</div>
                              </div>
                            </div>
                          ))
                        }
            </div>
          </div>
        </div>
      );
    
  • 类组件

    和类组件复制下面的代码。

    return (
          <div className="App">
            <div className="body">
              <form onSubmit={e => this.submit(e)} 
                                    style={{ 'padding': '0px 0px 12px 0px', }}>
                <input required 
                                         value={this.state.todo} 
                                         onChange={(e)=> this.setState({todo : e.target.value})} 
                                         type="text" placeholder='Enter TODO task'/>
                <button type='submit'>ADD TODO</button>
              </form>
              <div>
                <div style={{ 'padding': '0px 0px 12px 0px', }}>TODO's</div>
                {
                  this.props.list.map((todo,i) => (
                    <div className="todoCard" 
                                             key={i} 
                                             style={{'margin':'8px 0px 0px 0px'}}>
                      <div className="wrapper">
                        <div className="todoText">{todo.todo}</div>
                      </div>
                    </div>
                  ))
                }
              </div>
            </div>
          </div>
        )
    

哇,真是太好了,我们已经完成了一切,现在应该做得很好。

使用多个商店

现在,所有仅使用一个还原器或一家商店都可以很好地工作,在一个大型React项目中,您可以拥有多个商店,例如在我们的情况下,拥有一个拥有用户数据的商店,现在,如果我们想要要将用户的数据存储在与我们可以做的同一商店中,但这不是最佳实践,

最好的做法是在不同的文件中创建还原器,然后在存储文件夹中的index.js文件中导入它们,文件夹结构应该是此

Image description

现在,您可以通过像So so
这样的简化器来更新index.js文件

import {createStore} from 'redux'
import {TodoReducer}  from './Reducers/TodoReducer'
import { UserReducer } from './Reducers/UserReducer'

export const store = createStore(TodoReducer)

您可以看到,我们不再有一个还原器,但是我们只能直接将一个简化器直接传递给stestestore方法,因此我们如何解决这个大问题

不担心它和ABC一样简单。

首先,您必须从redux库中导入组合方法,然后将其传递到stestestore方法中,然后又可以接受包含所有导入还原器列表的对象。


import {combineReducers ,createStore} from 'redux'
import {TodoReducer}  from './Reducers/TodoReducer'
import { UserReducer } from './Reducers/UserReducer'

export const store = createStore(combineReducers({TodoReducer,UserReducer}))

现在知道我们不再有一个还原器,在我们的app.js或您要访问商店的组件中,访问不同商店中数据的方式会有所更改,您必须调用特定的商店想访问。

const mapStateToProps = (state) => ({
  list : state.TodoReducer.todos
    user : state.UserReducer
})

这样,我们已经成功地连接到了两个商店

您不必担心将数据分配到商店,因为它仍然可以正常工作。

您所要做的就是您在不同商店中不应该拥有相同的action.type案例,就像我们在Todoreducer商店中拥有case “ADD_TODO”一样,我们的UserReducer中不应该有case “ADD_TODO”

奖金

如果您尚未注意到或在现在使用Redux,但是一旦页面刷新,或者当您将数据刷新到另一页时,您的州出门时会出现数据,则商店中的数据清除了,请担心这是我们必须坚持状态的地方。

持久状态可帮助您持久数据,这意味着它有助于将数据保存在页面刷新之前清理数据以持续redux商店数据,我们必须安装redux-persist package

npm install redux-persist

它不会在这里结束,我们只是安装了现在必须使用的软件包,在使用它时,我们只需更新两个文件

  • 首先,我们的main.jsx或index.js文件位于SRC文件夹中,在此文件中,我们必须导入两件事

    import {PersistGate} from 'redux-persist/integration/react'
    import { persistStore } from 'redux-persist';
    

    导入此之后,我们必须将应用程序组件与persistgate包裹,并且persistgate具有称为persistor的属性,在此persistor中,我们通过persistStore方法传递,然后在persistStore方法中,我们要通过我们想要的东西传递。在我们的情况下,坚持哪种商店这就是您的代码的方式

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css';
    import App from './App';
    import { Provider } from 'react-redux';
    import { store } from './Store';
    import {PersistGate} from 'redux-persist/integration/react'
    import { persistStore } from 'redux-persist';
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <Provider store={store}>
          <PersistGate persistor={persistStore(store)}>
            <App />
          </PersistGate>
        </Provider>
      </React.StrictMode>
    );
    
  • 其次,在我们在index.js文件中的商店中,我们还将导入两件事

    import storage from "redux-persist/lib/storage";
    import { persistReducer } from "redux-persist";
    

    导入后,我们设置了要存储数据的配置,此配置容纳三件事

    const config = {
        key: 'root', // this is the name of the storage
        version:1, // the version of the storage
        storage, // storage that was imported from the redux-persist/lib/storage
    }
    

    现在,在您的导出中而不是将组合核法方法传递到strastore中,我们现在将PersistreDucer方法传递到streatestore方法中。

    现在,persistreducer将接收配置和组合形式,您可以查看下面的摘要

    import {combineReducers ,createStore} from 'redux'
    import {TodoReducer}  from './Reducers/TodoReducer'
    import { UserReducer } from './Reducers/UserReducer'
    import storage from "redux-persist/lib/storage";
    import { persistReducer } from "redux-persist";
    const config = {
        key: 'root',
        version:1,
        storage,
    }
    
    export const store = createStore(
        persistReducer(config,combineReducers({TodoReducer,UserReducer}))
    );
    

按照重新加载浏览器后的这两个简单步骤,您可以看到数据仍然保留

结论

将redux(redux-toolkit)添加到您的reactjs项目中,使您可以轻松地管理跨反应组件的数据,并使您的工作看起来很整洁且专业。

很棒的指导您可以从我的GitHub repository获取所有代码段,我也愿意参加任何相关问题或更多澄清