React的诱惑: React-Redux-三大原则和React-Redux-基本使用、优化、综合运用、其他组件使用

简介: React的诱惑: React-Redux-三大原则和React-Redux-基本使用、优化、综合运用、其他组件使用

Redux 三大原则


单一数据源

整个应用程序的 state 只存储在一个 store 中 Redux 并没有强制让我们不能创建多个 Store,但是那样做并不利于数据的维护 单一的数据源可以让整个应用程序的 state 变得方便维护、追踪、修改




State 是只读的

唯一修改 State 的方法一定是触发 action,不要试图在其他地方通过任何的方式来修改 State; 这样就确保了 View 或网络请求都不能直接修改 state,它们只能通过 action 来描述自己想要如何修改 stat; 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心 race condition(竟态)的问题;




使用纯函数来执行修改

通过 reducer 将旧 state 和 action 联系在一起,并且返回一个新的 State; 随着应用程序的复杂度增加,我们可以将 reducer 拆分成多个小的 reducers,分别操作不同 state tree 的一部分; 但是所有的 reducer 都应该是纯函数,不能产生任何的副作用





什么是纯函数


返回结果只依赖于它的参数,并且在执行过程里面没有副作用



纯函数

function sum(num1, num2){
    return num1 + num2;
}



const num1 = 10;
function sum(num2){
    return num1 + num2;
}


非纯函数

let num1 = 10;
function sum(num2){
    return num1 + num2;
}

官方文档:https://www.redux.org.cn/docs/introduction/ThreePrinciples.html





安装


安装稳定版:

npm install --save redux


index.js:

const redux = require('redux');
// 定义一个状态
let initialState = {
    count: 0
};
// 利用 store 来保存状态(state)
const store = redux.createStore(reducer);
// 利用 action 来修改状态
const addAction = {type: 'ADD_COUNT', num: 1};
const subAction = {type: 'SUB_COUNT', num: -1};
// 利用 reducer 将 store 和 action 串联起来
function reducer(state = initialState, action) {
    switch (action.type) {
        case 'ADD_COUNT':
            return {count: state.count + action.num};
        case 'SUB_COUNT':
            return {count: state.count - action.num};
        default:
            return state;
    }
}



监听状态的改变

store.subscribe(() => {
    console.log(store.getState());
});


从 Store 中获取存储的状态

console.log(store.getState());


修改 Store 中存储的状态

store.dispatch(addAction);


上面的处理方式实是存在问题的主要问题有以下几点:


  1. store、action、reducer 代码都写在一个文件中,不利于维护(后续文章解决)
  2. action 和 reducer 中都是使用字符串来指定和判断操作类型,写错不报错(本文当中进行解决)
  3. action 中的操作写死了,不够灵活(本文解决)

第二点的解决方案可以利用常量解决,第三点的解决方案可以利用函数解决,优化之后的代码如下:


const redux = require('redux');
const ADD_COUNT = 'ADD_COUNT';
const SUB_COUNT = 'SUB_COUNT';
// 定义一个状态
let initialState = {
    count: 0
};
// 利用store来保存状态(state)
const store = redux.createStore(reducer);
// 利用action来修改状态
const addAction = (num) => {
    return {type: ADD_COUNT, num: num};
};
const subAction = (num) => {
    return {type: SUB_COUNT, num: num};
};
// 利用reducer将store和action串联起来
function reducer(state = initialState, action) {
    switch (action.type) {
        case ADD_COUNT:
            return {count: state.count + action.num};
        case SUB_COUNT:
            return {count: state.count - action.num};
        default:
            return state;
    }
}




监听状态的改变

store.subscribe(() => {
    console.log(store.getState());
});


从 Store 中获取存储的状态

console.log(store.getState());


修改 Store 中存储的状态

store.dispatch(addAction(5));
store.dispatch(subAction(5));


综合运用(在React中使用)


上面文章当中说明了一个问题需要解决,在本文主要介绍的就是这个问题的解决方案;


  • store、action、reducer 代码都写在一个文件中,不利于维护

这个问题呢,可以在项目工程当中新建一个 store 文件夹,在该文件夹当中分别创建 action.jsconstants.jsreducer.jsstore.js 等文件:

  • action.js
import {
    ADD_COUNT,
    SUB_COUNT
} from './constants';
// 利用action来修改状态
export const addAction = (num) => {
    return {type: ADD_COUNT, num: num};
};
export const subAction = (num) => {
    return {type: SUB_COUNT, num: num};
};


  • constants.js
export const ADD_COUNT = 'ADD_COUNT';
export const SUB_COUNT = 'SUB_COUNT';


  • reducer.js
import {
    ADD_COUNT,
    SUB_COUNT
} from './constants';
// 定义一个状态
let initialState = {
    count: 666
};
// 利用reducer将store和action串联起来
function reducer(state = initialState, action) {
    switch (action.type) {
        case ADD_COUNT:
            return {count: state.count + action.num};
        case SUB_COUNT:
            return {count: state.count - action.num};
        default:
            return state;
    }
}
export default reducer;
  • store.js
import {createStore} from 'redux';
import reducer from './reducer';
// 利用store来保存状态(state)
const store = createStore(reducer);
export default store;




使用 Redux


  • App.js
import React from 'react';
import store from './store/store';
import {addAction, subAction} from './store/action';
class App extends React.PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            count: store.getState().count
        }
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({
                count: store.getState().count
            })
        })
    }
    componentWillUnmount() {
        store.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>
                    增加
                </button>
            </div>
        )
    }
    btnClick() {
        store.dispatch(addAction(5));
    }
}
export default App;




React-Redux-其它组件中使用


紧接着React-Redux-综合运用(在React中使用)的内容,下面介绍的是 Redux 在其它组件当中的使用以及注意点,在 src 目录下创建一个 component 目录在目录当中创建一个 home 与 about 组件,里面的内容是基于 app.js 进行参考得到的如下:


  • Home.js
import React from 'react';
import store from '../store/store';
import {addAction} from '../store/action';
class Home extends React.PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            count: store.getState().count
        }
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({
                count: store.getState().count
            })
        })
    }
    componentWillUnmount() {
        store.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>递增
                </button>
            </div>
        )
    }
    btnClick() {
        store.dispatch(addAction(1));
    }
}
export default Home;
  • About.js
import React from 'react';
import store from '../store/store';
import {subAction} from '../store/action';
class About extends React.PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            count: store.getState().count
        }
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({
                count: store.getState().count
            })
        })
    }
    componentWillUnmount() {
        store.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>递减
                </button>
            </div>
        )
    }
    btnClick() {
        store.dispatch(subAction(1));
    }
}
export default About;
  • App.js
import React from 'react';
import store from './store/store';
import {addAction} from './store/action';
import Home from './components/Home';
import About from './components/About';
class App extends React.PureComponent {
    constructor(props) {
        super(props);
        this.state = {
            count: store.getState().count
        }
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({
                count: store.getState().count
            })
        })
    }
    componentWillUnmount() {
        store.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onClick={() => {
                    this.btnClick()
                }}>
                    增加
                </button>
                <Home/>
                <About/>
            </div>
        )
    }
    btnClick() {
        store.dispatch(addAction(5));
    }
}
export default App;
  • 测试结果:

经过如上的一顿操作过后,发现代码存在的问题,就是重复代码过多,不利于维护,还有其它的一些问题,这里先不列举在下一篇文章,博主会全部统一一一进行介绍,当然还可以引出一个新的知识点。




最后


本期结束咱们下次再见👋~

🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗

相关文章
|
3天前
|
前端开发 JavaScript 开发者
React 按钮组件 Button
本文介绍了 React 中按钮组件的基础概念,包括基本的 `&lt;button&gt;` 元素和自定义组件。详细探讨了事件处理、参数传递、状态管理、样式设置和可访问性优化等常见问题及其解决方案,并提供了代码示例。帮助开发者避免易错点,提升按钮组件的使用体验。
104 77
|
4天前
|
前端开发 UED 开发者
React 对话框组件 Dialog
本文详细介绍了如何在 React 中实现一个功能完备的对话框组件(Dialog),包括基本用法、常见问题及其解决方案,并通过代码案例进行说明。从安装依赖到创建组件、添加样式,再到解决关闭按钮失效、背景点击无效、键盘导航等问题,最后还介绍了如何添加动画效果和处理异步关闭操作。希望本文能帮助你在实际开发中更高效地使用 React 对话框组件。
98 75
|
1月前
|
前端开发 JavaScript 测试技术
React 分页组件 Pagination
本文介绍了如何在 React 中从零构建分页组件,涵盖基础概念、常见问题及解决方案。通过示例代码详细讲解了分页按钮的创建、分页按钮过多、初始加载慢、状态管理混乱等常见问题的解决方法,以及如何避免边界条件、性能优化和用户反馈等方面的易错点。旨在帮助开发者更好地理解和掌握 React 分页组件的开发技巧,提升应用的性能和用户体验。
69 0
|
28天前
|
存储 缓存 JavaScript
如何优化React或Vue应用的性能
需要注意的是,性能优化是一个持续的过程,需要根据具体的应用场景和性能问题进行针对性的优化。同时,不同的项目和团队可能有不同的优化重点和方法,要结合实际情况灵活运用这些优化策略,以达到最佳的性能效果。
107 51
|
9天前
|
前端开发 Java API
React 进度条组件 ProgressBar 详解
本文介绍了如何在 React 中创建进度条组件,从基础实现到常见问题及解决方案,包括动态更新、状态管理、性能优化、高级动画效果和响应式设计等方面,帮助开发者构建高效且用户体验良好的进度条。
37 18
|
11天前
|
前端开发 UED 开发者
React 选项卡组件 Tabs:从基础到优化
本文详细介绍了如何在React中构建一个功能丰富的选项卡组件,包括基础实现、样式美化、常见问题及解决方法。通过逐步讲解,从简单的选项卡组件结构开始,逐步引入样式、性能优化、动态内容加载、键盘导航支持和动画效果,最后讨论了自定义样式的实现。旨在帮助开发者在React项目中高效构建高质量的选项卡组件。
47 18
|
1天前
|
存储 前端开发 UED
React 面包屑组件 Breadcrumb 详解
面包屑导航是现代Web应用中常见的UI元素,帮助用户了解当前位置并快速返回上级页面。本文介绍如何使用React构建面包屑组件,涵盖基本概念、实现方法及常见问题。通过函数式组件和钩子,结合React Router动态生成路径,处理嵌套路由,并确保可访问性。示例代码展示了静态和动态面包屑的实现,帮助开发者提升用户体验。
89 73
|
24天前
|
存储 前端开发 测试技术
React组件的最佳实践
React组件的最佳实践
|
16天前
|
前端开发 UED
React 文本区域组件 Textarea:深入解析与优化
本文介绍了 React 中 Textarea 组件的基础用法、常见问题及优化方法,包括状态绑定、初始值设置、样式自定义、性能优化和跨浏览器兼容性处理,并提供了代码案例。
42 8
|
22天前
|
前端开发 API 开发者
React 文件上传组件 File Upload
本文详细介绍了如何在 React 中实现文件上传组件,从基础的文件选择和上传到服务器,再到解决文件大小、类型限制、并发上传等问题,以及实现多文件上传、断点续传和文件预览等高级功能,帮助开发者高效构建可靠的应用。
49 12