React study

本文深入探讨React结合React Router实现的导航功能,展示了如何利用React Hooks更新状态,以及通过Redux进行状态管理的完整示例,包括自定义中间件的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

react

路由

import React from 'react'
import {HashRouter  , Route, Link  } from "react-router-dom"

class App extends React.Component {

    render() {
        return (
            <HashRouter> 
             {/* 这个div必须有  */}
                <div> 
                   <Link to="/A">A</Link>
                   <Link to="/B">B</Link>
                    <div>
                        <Route exact path="/A" component={ ()=>{return <div>click A</div>} }/>
                        <Route path="/B" component={()=>{return <div>click B</div>} } />
                    </div>
                </div>   
            </HashRouter>
        );
    }
}

export default App;

ReactHooks

https://jspang.com/posts/2019/08/12/react-hooks.html

import React,{useState} from 'react'

function ExampleHook() {
        const [count,setCount]=useState(0)
        return (
            <div>
                ---{count}--
                <button onClick={()=>{setCount(count+1)}}>gggggg</button>
            </div>
        );
}

export default ExampleHook;

Redux简单demo

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux'  //  引入createStore方法
import { Provider,connect } from 'react-redux'


const defalutState = {
    inputValue : 'test01',
    list :[]
}

const reducer=(state = defalutState,action) =>{
    if(action.type === 'change_input'){
        let newState = JSON.parse(JSON.stringify(state))
        newState.inputValue = action.value
        return newState
    }
    //----关键代码------start---------
    if(action.type === 'add_item'){
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.push(newState.inputValue)
        newState.inputValue = ''
        return newState
    }
    //----关键代码------end---------
    return state
}

const store = createStore(reducer); // 创建数据存储仓库


const TodoList =(props)=>{
    let {inputValue ,inputChange,clickButton,list} = props; // 粘贴过来后,此处要进行修改
    return (
        <div>
            <div>
                <input value={inputValue} onChange={inputChange} />
                <button onClick={clickButton}>提交</button>
            </div>
            <ul>
                {
                    list.map((item,index)=>{
                        return (<li key={index}>{item}</li>)
                    })
                }
            </ul>
        </div>
    );
}

const stateToProps = (state)=>{
    return {
        inputValue : state.inputValue,
        list:state.list
    }
}
const dispatchToProps = (dispatch) =>{
    return {
        inputChange(e){
            let action = {
                type:'change_input',
                value:e.target.value
            }
            dispatch(action)
        },
        clickButton(){
            let action = {
                type:'add_item'
            }
            dispatch(action)
        }
    }
}

const CtodoList= connect(stateToProps,dispatchToProps)(TodoList)

const App = (
   <Provider store={store}>
       <CtodoList />
   </Provider>
)
//---------关键代码--------end
ReactDOM.render(App, document.getElementById('root'));

redux自定义中间件与connect函数

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore , applyMiddleware ,compose } from 'redux'  //  引入createStore方法
//import thunk from 'redux-thunk'
import { Provider,connect } from 'react-redux'

const defalutState = {
    inputValue : 'test01',
    list :[]
}

const reducer=(state = defalutState,action) =>{
    if(action.type === 'change_input'){
        let newState = JSON.parse(JSON.stringify(state))
        newState.inputValue = action.value
        return newState
    }
    //----关键代码------start---------
    if(action.type === 'add_item'){
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.push(newState.inputValue)
        newState.inputValue = ''
        return newState
    }
    //----关键代码------end---------
    return state
}




const myMiddleware = (store) => (next) => (action) => {
    console.log('进入了我自己定义的中间件');
    let result = next(action);    // 执行下一步
    // let result = store.dispatch(action); //不调用next,直接使用store.dispatch调用原生。然后是不行的,会陷入dispatch死循环。
    return result;
}

//

const store = createStore(reducer,applyMiddleware(myMiddleware)); // 创建数据存储仓库


const TodoList =(props)=>{
    let {inputValue ,inputChange,clickButton,list} = props; // 粘贴过来后,此处要进行修改
    return (
        <div>
            <div>
                <input value={inputValue} onChange={inputChange} />
                <button onClick={clickButton}>提交</button>
            </div>
            <ul>
                {
                    list.map((item,index)=>{
                        return (<li key={index}>{item}</li>)
                    })
                }
            </ul>
        </div>
    );
}

const stateToProps = (state)=>{
    return {
        inputValue : state.inputValue,
        list:state.list
    }
}
const dispatchToProps = (dispatch) =>{
    return {
        inputChange(e){
            let action = {
                type:'change_input',
                value:e.target.value
            }
            dispatch(action)
        },
        clickButton(){
            let action = {
                type:'add_item'
            }
            dispatch(action)
        }
    }
}

const CtodoList= connect(stateToProps,dispatchToProps)(TodoList)

const App = (
   <Provider store={store}>
       <CtodoList />
   </Provider>
)
//---------关键代码--------end
ReactDOM.render(App, document.getElementById('root'));

redux-thunk的源码非常简洁,要理解它需要看最后一部分

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

Redux实现细节

https://minglie.github.io/html/reactDemo/React-Redux-connect/index.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.bootcss.com/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.bootcss.com/babel-standalone/6.26.0/babel.min.js"></script>
    <!--<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>-->


</head>

<body>

<div id="example" class="example"></div>

</body>
</html>










<script  type="text/babel">
    //返回函数集 functions 组合后的复合函数, 也就是一个函数执行完之后把返回的结果再作为参数赋给下一个函数来执行.
    const compose = (...func) => (...init) => {
        let result;
        switch (func.length) {
            case 0:
                result = func; break;
            case 1:
                result = func[0](...init); break;
            default:
                result = func.reduce((x, y) => {
                    return typeof x === 'function' ? y(x(...init)) : y(x);
                }); break;
        }
        return result;
    }


    //添加中间件
    function applyMiddleware(...middlewares) {
        return createStore => (reducer, preloadedState, enhancer) => {
            const store = createStore(reducer, preloadedState, enhancer)
            let dispatch = store.dispatch
            let chain = [] //用于存放中间件
            const middlewareAPI = {
                getState: store.getState,
                dispatch: (action) => store.dispatch(action)
            }
            chain = middlewares.map(middleware => middleware(middlewareAPI))
            dispatch = compose(...chain)(store.dispatch)
            return {
                ...store,
                dispatch
            }
        }
    }
    //Redux核心代码
    const Redux={
        currentReducer:{},
        currentState:{},
        currentListeners:{},
        createStore: function createStore(reducer, preloadedState, enhancer) {
            // 如果 preloadedState类型是function,enhancer类型是undefined,那认为用
            // 户没有传入preloadedState,就将preloadedState的值传给
            // enhancer,preloadedState值设置为undefined
            if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
                enhancer = preloadedState
                preloadedState = undefined
            }
            // enhancer类型必须是一个function
            if (typeof enhancer !== 'undefined') {
                if (typeof enhancer !== 'function') {
                    throw new Error('Expected the enhancer to be a function.')
                }
                // 返回使用enhancer增强后的store
                return enhancer(Redux.createStore)(reducer, preloadedState)
            }
            // reducer必须是一个function
            if (typeof reducer !== 'function') {
                throw new Error('Expected the reducer to be a function.')
            }
            Redux.currentState=reducer(preloadedState,{type:0});
            Redux.currentReducer = reducer;
            Redux.currentListeners = [];
            let isDispatching = false


            function dispatch(action) {
                if (typeof action.type === 'undefined') {
                    throw new Error(
                        'Actions may not have an undefined "type" property. ' +
                        'Have you misspelled a constant?'
                    )
                }
                // reducer内部不允许再次调用dispatch,否则抛出异常
                if (isDispatching) {
                    throw new Error('Reducers may not dispatch actions.')
                }
                try {
                    isDispatching = true
                    Redux.currentState = Redux.currentReducer(Redux.currentState, action);
                } finally {
                    isDispatching = false
                }
                var listeners = Redux.currentListeners;
                for (var i = 0; i < listeners.length; i++) {
                    var listener = listeners[i];
                    listener();
                }
                return action;
            }


            function subscribe(listener) {
                Redux.currentListeners.push(listener);
            }
            function getState() {
                return Redux.currentState;
            }
            return{
                dispatch, subscribe, getState
            }
        }
    };
    //redux 中间件例子
    const myMiddleware = (store) => (next) => (action) => {
        console.log('进入了我自己定义的中间件');
        let result = next(action);    // 执行下一步
        // let result = store.dispatch(action); //不调用next,直接使用store.dispatch调用原生。然后是不行的,会陷入dispatch死循环。
        return result;
    }

    ////////////////下面两个是action/////////////////////////////////////////
    const increment = (num)=> {
        return {
            type: 'INCREMENT_COUNTER',
            num:num
        }
    };
    const decrement = ()=> {
        return {type: 'DECREMENT_COUNTER'}
    };

    const actions={
        increment,
        decrement
    };
    //定义一个计数reduce,用于创建store
    const counterReduce= (defaultState={count: 10}, action)=> {
        console.log("进入reducer 状态:",defaultState);
        switch (action.type) {
            case 'INCREMENT_COUNTER':
                return {
                    count: defaultState.count+action.num
                };
            case 'DECREMENT_COUNTER':
                return {
                    count: defaultState.count-1
                };
            default:
                return defaultState;
        }
    };

    //创建全局唯一store
    let store =  Redux.createStore(counterReduce,applyMiddleware(myMiddleware));


   //connect是一个高阶组件(输入输出都是组件的函数)
    // 1,接受一个组件,把数据放到组件内部,返回一个组件
    // 2,数据发生变化的时候,通知到组件
    const connect =(mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
        class Connect extends React.Component {
            constructor () {
                super();
                this.state = {
                    allProps: {}
                }
            }
            componentWillMount () {
                this._updateProps();
                store.subscribe(() => this._updateProps())
            }
            _updateProps () {
                let stateProps = mapStateToProps ? mapStateToProps(store.getState(), this.props):{}; // 防止 mapStateToProps 没有传入
                let dispatchProps = mapDispatchToProps ? mapDispatchToProps(store.dispatch, this.props):{}; // 防止 mapDispatchToProps 没有传入
                this.setState({
                    allProps: {
                        ...stateProps,
                        ...dispatchProps,
                        ...this.props
                    }
                })
            }
            render () {
                return <WrappedComponent {...this.state.allProps} />
            }
        }
        return Connect
    };

   //测试用的计数组件
    class Counter extends React.Component {
        render() {
            //从组件的props属性中导入四个方法和一个变量
            const {increment, decrement, counter} = this.props;
            //渲染组件,包括一个数字,四个按钮
            return(
                    <div>
                        Clicked: {counter} times
                        <button onClick={()=>{increment(3)}}>+</button>
                        {' '}
                        <button onClick={decrement}>-</button>
                        {' '}
                    </div>
            )
        }
    }
    //将state.counter绑定到props的counter
    //这个函数允许我们将 store 中的数据作为 props 绑定到组件上。
    const mapStateToProps = (state) => {
        return {
            counter: state.count
        }
    };

    //它的功能是,将 触发action的函数 作为props 绑定到组件上,
    const mapDispatchToProps = (dispatch, ownProps) => {
        return {
            increment: (...args) => dispatch(actions.increment(...args)),
            decrement: (...args) => dispatch(actions.decrement(...args))
        }
    };
    //Counter 经过 connect 加强得到 App
    const App=connect(mapStateToProps, mapDispatchToProps)(Counter);
</script>



<script type="text/babel">
    ReactDOM.render(
            <div>
                <App />
            </div>,
        document.getElementById('example')
    );
</script>








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值