redux入门学习

Redux学习

redux 的工作流是单向数据流

react 组件相当于借书者

action相当于图书管理员

store相当于图书馆

reducers是图书管理软件

react-action-store-reducers-store-react

步骤

1.用react脚手架创建一个新的项目

2.visual studio code安装simple react snippet 插件

3.然后再src目录下新建一个文件,TodoList.jsx

在使用到snippet的地方 , 用快捷键ccc来生成react代码片段

4.安装antd组件制作UI界面

npm install antd --save-dev

5.使用antd制作UI界面

编辑文件(TodoList.jsx),如下代码,这样,基本的列表框就已经实现了(TodoList.jsx)

import React, { Component } from "react";
import 'antd/dist/antd.css';
import { Input, Button, List } from "antd";

const data = [
    '早8点开晨会',
    '早10点开晨会1',
    '早12点开晨会2'
]

class TodoList extends Component {
    render() {
        return (
            <div>
                <div style={{ margin: '2rem' }}>
                    <Input placeholder="write something" style={{ width: '250px', marginRight: '10px' }}></Input>
                    <Button type="primary">增加</Button>
                </div>
                <div style={{ margin: '10px', width: '300px' }}>
                    <List
                        bordered
                        dataSource={data}
                        renderItem={item => <List.Item>{item}</List.Item>}
                    />

                </div>
            </div>
        );
    }
}

export default TodoList;

6.安装redux

npm install redux --save-dev

7.创建redux中的仓库-store和reducer

在src目录新建文件夹store,在store目录下面文件新建index.js文件,代码如下,该文件用于新建仓库

import { createStore } from 'redux'
//建立仓库
const store = createStore();

export default store;

在store目录下新建reducer.js文件,该文件类似管理员的角色,代码如下

const defaultState = {};

export default (state = defaultState, action) => {
    return state;
}

最后修改index.js文件,将reducer引入到仓库里面,index.js文件代码如下,这样我们就将reducer和仓库建立了联系。

import { createStore } from 'redux'
import reducer from './reducer'


//建立仓库
const store = createStore(reducer);

export default store;

8.如何将TodoList里面的功能用redux实现呢?

首先将初始值存储到reducer.js文件,代码如下:

const defaultState = {
    inputValue: 'Write something',
    list: [
        '早8点开晨会',
        '早10点开晨会1',
        '早12点开晨会2'
    ]
};

export default (state = defaultState, action) => {
    return state;
}

然后在TodoList.js文件里面删除初始值,引入store,如下代码,刷新页面发现也可以正常显示了

import React, { Component } from "react";
import 'antd/dist/antd.css';
import { Input, Button, List } from "antd";
import store from './store/'


class TodoList extends Component {
    constructor(props) {
        super(props);
        console.log(store.getState())
        this.state=store.getState();
    }

    render() {
        return (
            <div>
                <div style={{ margin: '2rem' }}>
                    <Input placeholder={this.state.inputValue}
                    style={{ width: '250px', marginRight: '10px' }}></Input>
                    <Button type="primary">增加</Button>
                </div>
                <div style={{ margin: '10px', width: '300px' }}>
                    <List
                        bordered
                        dataSource={this.state.list}
                        renderItem={item => <List.Item>{item}</List.Item>}
                    />

                </div>
            </div>
        );
    }
}

export default TodoList;

安装google浏览器插件Redux DevTools,但是发现redux工具还使用不了

去网页上可以https://github.com/zalmoxisus/redux-devtools-extension#usage 可以看到使用redux的基本过程,修改store/index.js代码,代码如下所示:

import { createStore } from 'redux'
import reducer from './reducer'


//建立仓库
const store = createStore(
    reducer,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

这样就可以在浏览器中使用redux dev tools工具了。

9.通过input体验Redux的流程

通过给input 添加动态变化事件来体验redux的过程,如下代码,给input添加onChange事件,然后通过dipatch将action通知到reducer那边,TodoList.js代码如下。

import React, { Component } from "react";
import 'antd/dist/antd.css';
import { Input, Button, List } from "antd";
import store from './store/'


class TodoList extends Component {
    constructor(props) {
        super(props);
        console.log(store.getState())
        this.state = store.getState();
        this.changeInputValue = this.changeInputValue.bind(this);
    }

    changeInputValue(e) {
        console.log(e.target.value);
        const action = {
            type: 'changeInput',
            value: e.target.value
        }
        store.dispatch(action);
    }

    render() {
        return (
            <div>
                <div style={{ margin: '2rem' }}>
                    <Input placeholder={this.state.inputValue}
                        style={{ width: '250px', marginRight: '10px' }}
                        onChange={this.changeInputValue}
                    ></Input>
                    <Button type="primary">增加</Button>
                </div>
                <div style={{ margin: '10px', width: '300px' }}>
                    <List
                        bordered
                        dataSource={this.state.list}
                        renderItem={item => <List.Item>{item}</List.Item>}
                    />

                </div>
            </div>
        );
    }
}

export default TodoList;

在reducer.js文件中打印出action,就会发现action的内容如下,

const defaultState = {
    inputValue: 'Write something',
    list: [
        '早8点开晨会',
        '早10点开晨会1',
        '早12点开晨会2'
    ]
};

export default (state = defaultState, action) => {
    console.log(action);
    //{type: "changeInput", value: "ggggfffffffffffffffffff"}
    //reducer里面只能接受state,不能改变state
    return state;
}

当每次改变文本框的值时,就会通知到reducer这边,action的内容就会被传递到这里。

reducer里面只能接受state,不能改变state,如果想要修改state里面内容呢,index.js代码如下:

刷新页面,可以看到state里面的变量值已经发生了变化。

const defaultState = {
    inputValue: 'Write something',
    list: [
        '早8点开晨会',
        '早10点开晨会1',
        '早12点开晨会2'
    ]
};

export default (state = defaultState, action) => {
    console.log(state, action);
    //reducer里面只能接受state,不能改变state
    if (action.type == 'changeInput') {
        //
        let newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value;
        return newState;
    }
    return state;
}

当时这里有个问题就是当设置了input的value值,必须要有一个redux的订阅动作,state里面的变量才会刷新,如果没有这个订阅,则不会刷新,TodoList.js代码如下所示。

import React, { Component } from "react";
import 'antd/dist/antd.css';
import { Input, Button, List } from "antd";
import store from './store/'


class TodoList extends Component {
    constructor(props) {
        super(props);
        console.log(store.getState())
        this.state = store.getState();
        this.changeInputValue = this.changeInputValue.bind(this);
        this.storeChange = this.storeChange.bind(this);
    }

    changeInputValue(e) {
        console.log(e.target.value);
        const action = {
            type: 'changeInput',
            value: e.target.value
        }
        store.dispatch(action);
        store.subscribe(this.storeChange);
    }

    storeChange() {
        this.setState(store.getState())
    }

    render() {
        return (
            <div>
                <div style={{ margin: '2rem' }}>
                    <Input placeholder={this.state.inputValue}
                        style={{ width: '250px', marginRight: '10px' }}
                        onChange={this.changeInputValue}
                        value={this.state.inputValue}
                    ></Input>
                    <Button type="primary">增加</Button>
                </div>
                <div style={{ margin: '10px', width: '300px' }}>
                    <List
                        bordered
                        dataSource={this.state.list}
                        renderItem={item => <List.Item>{item}</List.Item>}
                    />

                </div>
            </div>
        );
    }
}

export default TodoList;

10.通过input体验Redux的流程

给按钮添加功能函数,当增加按钮被点击时,下面的list组件就会发生变化,

TodoList.js文件代码如下所示:通过store.dispatch(action) 函数发送给reducers。

import React, { Component } from "react";
import 'antd/dist/antd.css';
import { Input, Button, List } from "antd";
import store from './store/'


class TodoList extends Component {
    constructor(props) {
        super(props);
        console.log(store.getState())
        this.state = store.getState();
        this.changeInputValue = this.changeInputValue.bind(this);
        this.storeChange = this.storeChange.bind(this);
        this.clickBtn = this.clickBtn.bind(this);
    }

    changeInputValue(e) {
        console.log(e.target.value);
        const action = {
            type: 'changeInput',
            value: e.target.value
        }
        store.dispatch(action);
        store.subscribe(this.storeChange);
    }

    storeChange() {
        this.setState(store.getState())
    }

    clickBtn() {
        const action = { type: 'addItem' }
        store.dispatch(action);
    }

    render() {
        return (
            <div>
                <div style={{ margin: '2rem' }}>
                    <Input placeholder={this.state.inputValue}
                        style={{ width: '250px', marginRight: '10px' }}
                        onChange={this.changeInputValue}
                        value={this.state.inputValue}
                    ></Input>
                    <Button type="primary" onClick={this.clickBtn}>增加</Button>
                </div>
                <div style={{ margin: '10px', width: '300px' }}>
                    <List
                        bordered
                        dataSource={this.state.list}
                        renderItem={item => <List.Item>{item}</List.Item>}
                    />

                </div>
            </div>
        );
    }
}

export default TodoList;

相应地,Reducer.js 文件内容也要添加这个action相关的内容 ,当识别到增加按钮发来的action时,将state状态更新。代码如下所示:

const defaultState = {
    inputValue: 'Write something',
    list: [
        '早8点开晨会',
        '早10点开晨会1',
        '早12点开晨会2'
    ]
};

export default (state = defaultState, action) => {
    console.log(state, action);
    //reducer里面只能接受state,不能改变state
    if (action.type === 'changeInput') {
        //
        let newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value;
        return newState;
    }

    if (action.type === 'addItem') {
        let newState = JSON.parse(JSON.stringify(state));
        newState.list.push(newState.inputValue);
        newState.inputValue = '';
        return newState;
    }
    return state;
}

当点击添加按钮之后,input文本框的内容置空,列表框也会增加内容了。这是因为TodoList.js文件中,已经订阅过相关内容,store.subscribe(this.storeChange) 当store里面的state内容 发生变化时,界面也会相应发生变化。如果将订阅的代码去掉,则界面不会发生变化。

11.用Redux实现TodoList的删除功能

猜你喜欢

转载自www.cnblogs.com/zdjBlog/p/12614342.html