美文网首页
六、使用redux管理数据

六、使用redux管理数据

作者: 风之伤_3eed | 来源:发表于2019-12-12 11:00 被阅读0次

    一、安装redux 、redux-pack、redux-thunk

    npm i redux redux-pack redux-thunk
    参考网站:reduxredux-thunkredux-pack

    二、在src/config下新建store.ts文件写入

    import { createStore, applyMiddleware } from 'redux';
    import thunkMiddleware from 'redux-thunk'; // 实现异步发送请求
    import { middleware as reduxPackMiddleware } from 'redux-pack';
    import rootReducer from '../reducers';
    
    const store = createStore(
      rootReducer,
      applyMiddleware(thunkMiddleware, reduxPackMiddleware)
    );
    
    export default store
    

    三、新建src/actions文件夹

    actions 文件夹下index.ts只负责统一导出
    actions文件夹下新建user.ts写如如下代码

    import { api } from '../config';
    import { wrapServer } from '../config/axios'
    
    export enum ACTION_TYPE {
      LOGIN = 'LOGIN',
      LOGOUT = 'LOGOUT'
    }
    
    export const login = (data: any) => {
      return {
        type: ACTION_TYPE.LOGIN,
        promise: wrapServer({
          method: 'post',
          url: api.login,
          data,
        }),
      };
    };
    
    export const logout = () => {
      return {
        type: ACTION_TYPE.LOGOUT,
        promise: wrapServer({
          method: 'post',
          url: api.logout,
        }),
      };
    };
    
    export default {
      ACTION_TYPE,
    };
    

    注:actions文件夹下不同文件负责不同模块下的请求,如果有新的模块可以在actions文件夹下新建相对应的文件,在同一模块下新增请求需要在ACTION_TYPE添加一个唯一type,导出一个新的请求。

    四、新建src/reducers文件夹

    新建index.tsx文件写入如下代码(每新增一个reducers文件下的文件需要在该文件内通过combineReducers合并)

    import { combineReducers } from 'redux';
    
    import { default as user } from './user';
    
    export default combineReducers({
      user,
    })
    

    新建user.ts文件写入如下代码(在这里可以对返回后的数值进行处理)

    import { handle } from 'redux-pack';
    import { User } from '../actions';
    
    const { ACTION_TYPE } = User;
    
    // 写入请求前默认数值
    const initialState = {
      user: {}
    }
     
    export default (state = initialState, action: any) => {
      const { type, payload } = action;
      switch (type) {
        // 根据唯一type来匹配相应action 
        case ACTION_TYPE.LOGIN:
          return handle(state, action, {
            start: prevState => ({ ...prevState, loading: true}),
            finish: prevState => ({ ...prevState, loading: false }),
            failure: prevState => ({ ...prevState, user: state.user }),
            success: prevState => ({ ...prevState, user: payload.data }),
          });
       default:
          return state;
      }
    }
    

    五、还需在src/App.tsx文件下引入Provider和store

    修改src/App.tsx文件

    import React from "react";
    import {
      BrowserRouter as Router,
      Switch,
      Route,
    } from "react-router-dom";
    import  Login from './pages/login';
    import Layout from './layout';
    import { Provider } from 'react-redux';
    import store from './config/store';
    import 'rsuite/dist/styles/rsuite-default.css';
    import "./App.css";
    
    const App = () => {
      return (
        <Provider store={store}>
        <Router>
          <Switch>
            <Route exact path="/login" 
            component = {(props: any) => <Login { ...props } /> }
            />
            <Route path="/" 
            component = {(props: any) => <Layout { ...props } /> }
            />
          </Switch>
        </Router>
        </Provider>
      );
    };
    
    export default App;
    

    六、在页面发送请求接收数据
    在src/pages/login修改index.tsx文件
    引入connect

    import { connect } from 'react-redux';
    

    发送及从redux获取参数

    const mapDispatchToProps = (dispatch: any) => ({
      login: (value: any) => dispatch(login(value)),
    });
    
    const mapStateToProps = (user: any) => ({ user });
    

    使用connect连接redux

    export default connect(mapStateToProps, mapDispatchToProps)(Login);
    

    页面完整代码

    import React, { useState } from "react";
    import { connect } from 'react-redux';
    import {
      Container,
      Content,
      FlexboxGrid,
      Panel,
      Form,
      FormGroup,
      ControlLabel,
      FormControl,
      ButtonToolbar,
      Button,
      Schema
    } from "rsuite";
    import {
      login
    } from '../../actions/user';
    import { setToken } from '../../config/localStorage';
    import './login.css';
    
    const { StringType } = Schema.Types;
    
    const mapDispatchToProps = (dispatch: any) => ({
      login: (value: any) => dispatch(login(value)),
    });
    
    const mapStateToProps = (user: any) => ({ user });
    
    interface Props {
      history: any;
      login: (value: any) => any;
      user: any;
    }
    
    const Login = (props: Props) => {
      const [formValue, setFormValue] = useState<any>({
        name: '',
        password: ''
      });
      const [form, setForm] = useState<any>(null);
      
      // 自定义表单规则
      const asyncCheckUsername = (name: any): any => {
        console.log(name)
        return new Promise(resolve => {
          setTimeout(() => {
            if (name === 'abc') {
              resolve(false);
            } else {
              resolve(true);
            }
          }, 500);
        });
      }
    
      // 验证表单规则
      const model = Schema.Model({
        name: StringType()
          .isRequired('请填写用户名.')
          .addRule((value, data) => {
            return asyncCheckUsername(value);
          }, '用户已注册'),
        password: StringType()
        .isRequired('请填写密码.')
      });
    
      // 提交
      const handleSubmit = () => {
        form.checkAsync().then((result: any) => {
          if (!result.hasError) {
            发送登录请求
            props.login(formValue)
            .then(
              (res: any) => {
                if (!res.error) {
                  // 当登录成功时时跳转到控制台首页
                  setToken(res.payload.data)
                  props.history.push('/')
    
                }
              }
            )
          }
        });
      }
    
      return (
        <div className="show-fake-browser login-page">
          <Container>
            <Content>
              <FlexboxGrid justify="center">
                <FlexboxGrid.Item colspan={12}>
                  <Panel header={<h3>登录</h3>} bordered>
                    <Form 
                     ref={(ref: any) => (setForm(ref))}
                    fluid
                    onChange={formValue => {
                      setFormValue(formValue)
                    }}
                    onCheck={formError => {
                    }}
                    formValue={formValue}
                    model={model}
                    >
                      <FormGroup>
                        <ControlLabel>用户名</ControlLabel>
                        <FormControl name="name" />
                      </FormGroup>
                      <FormGroup>
                        <ControlLabel>密码</ControlLabel>
                        <FormControl name="password" type="password" />
                      </FormGroup>
                      <FormGroup>
                        <ButtonToolbar>
                          <Button appearance="primary" onClick={handleSubmit}>登录</Button>
                          {/* <Button appearance="link">Forgot password?</Button> */}
                          <span style={{paddingLeft: 20}}>用户名:admin 密码:123456</span>
                        </ButtonToolbar>
                      </FormGroup>
                    </Form>
                  </Panel>
                </FlexboxGrid.Item>
              </FlexboxGrid>
            </Content>
            {/* <Footer>xxx公司</Footer> */}
          </Container>
        </div>
      );
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(Login);
    

    相关文章

      网友评论

          本文标题:六、使用redux管理数据

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