首页 > 其他分享 >redux-first-history

redux-first-history

时间:2024-09-08 14:23:20浏览次数:13  
标签:return js history action import redux first

redux-first-history

  • 这是一个把redux仓库和路由连接的库
  • 它有两个作用
    • 把地址栏中的新的路径保存到redux仓库中
    • 可以通过派发动作的方式跳转路径

生成项目

create-react-app hs_redux_first_history
cd hs_redux_first_history
npm install redux react-redux  react-router-dom redux-first-history --save

跑通项目

2.1 src\index.js

src\index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Routes, Link } from "react-router-dom";
import { HistoryRouter } from "./redux-first-history/rr6";
import { Provider } from 'react-redux';
import { store, history } from "./store";
import Home from './components/Home';
import Counter from './components/Counter';
ReactDOM.render(
  <Provider store={store}>
    <HistoryRouter history={history}>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/counter">Counter</Link></li>
      </ul>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/counter" element={<Counter />} />
      </Routes>
    </HistoryRouter>
  </Provider >,
  document.getElementById('root')
);

2.2 history.js

src\history.js

import { createBrowserHistory } from 'history';
import { createReduxHistoryContext } from "./redux-first-history";
const history = createBrowserHistory();
const { routerReducer, routerMiddleware, createReduxHistory } = createReduxHistoryContext({ history });
export {
    routerReducer,
    routerMiddleware,
    createReduxHistory
}

2.3 store\index.js

src\store\index.js

import { createStore, applyMiddleware } from 'redux';
import combinedReducer from './reducers';
import { routerMiddleware, createReduxHistory } from '../history';
//routerMiddleware 可以拦截到 push('/counter') 这个action,调用history进行路径的跳转
export const store = applyMiddleware(routerMiddleware)(createStore)(combinedReducer);
window.store = store;
export const history = createReduxHistory(store);

2.4 action-types.js

src\store\action-types.js

export const ADD = 'ADD';
export const MINUS = 'MINUS';

2.5 counter.js

src\store\reducers\counter.js

import * as actionTypes from '../action-types';
function counter(state = { number: 0 }, action) {
    switch (action.type) {
        case actionTypes.ADD:
            return { number: state.number + 1 };
        case actionTypes.MINUS:
            return { number: state.number - 1 };
        default:
            return state;
    }
}
export default counter;

2.6 reducers\index.js

src\store\reducers\index.js

import { combineReducers } from 'redux';
import counter from './counter';
import { routerReducer } from '../../history';
const reducers = {
    counter,
    router: routerReducer
}
export default combineReducers(reducers);

2.7 Home.js

src\components\Home.js

import React from 'react';
import { useDispatch } from 'react-redux';
import { push } from "../redux-first-history";
function Home() {
    //const navigate = useNavigate();
    const dispatch = useDispatch();
    const gotoCounter = () => {
        // navigate('/counter');
        dispatch(push('/counter'));
    }
    return (
        <div>
            <p>Home</p>
            <button onClick={gotoCounter}>跳转到/counter</button>
        </div>
    )
}
export default Home;

2.9 Counter.js

src\components\Counter.js

function Counter() {
    return (
        <div>
            <p>Counter</p>
        </div>
    )
}
export default Counter;

实现

3.1 redux-first-history\index.js

src\redux-first-history\index.js

export { push } from './actions';
export { createReduxHistoryContext } from './create';

3.2 actions.js

src\redux-first-history\actions.js

//调用历史对象的方法
export const CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD';
//当路径变更后会派发这个动作给仓库,让仓库中reducer把最新的路径放入仓库状态中
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE';

export function locationChangeAction(location, action) {
  return {
    type: LOCATION_CHANGE,
    payload: { action, location }
  }
}

function updateLocation(method) {
  return (...args) => {
    return {
      type: CALL_HISTORY_METHOD,
      payload: { method, args }
    }
  }
}

export const push = updateLocation('push');

3.3 create.js

src\redux-first-history\create.js

import { createRouterMiddleware } from './middleware';
import { push, locationChangeAction } from './actions';
import { createRouterReducer } from './reducer';
/**
 * 创建redux版本的history 上下文
 * @param {*} history 原始的history对象  
 */
export function createReduxHistoryContext({ history }) {
  const routerMiddleware = createRouterMiddleware(history);
  const routerReducer = createRouterReducer(history);
  function createReduxHistory(store) {
    store.dispatch(locationChangeAction(history.location, history.action));
    //订阅路径变化事件,当路径发生变化后重新添发动作给仓库,重新保存路径
    history.listen(({ location, action }) => {
      store.dispatch(locationChangeAction(location, action));
    });
    return {
      createHref: history.createHref,
      push: (...args) => store.dispatch(push(...args)),//history.push('/counter');
      listen: history.listen,
      get location() {//原来获取路径是从history对象上取的,现在是从仓库中取
        return store.getState().router.location;
      },
      get action() {
        return store.getState().router.action;
      }
    };
  }
  return {
    routerMiddleware,
    createReduxHistory,
    routerReducer
  }
}

3.4 middleware.js

src\redux-first-history\middleware.js

import { CALL_HISTORY_METHOD } from './actions'

export function createRouterMiddleware(history) {
  return function () {
    return function (next) {
      return function (action) {
        if (action.type !== CALL_HISTORY_METHOD) {
          return next(action);
        }
        const { method, args } = action.payload;
        history[method](...args);
      }
    }
  }
}

3.5 reducer.js

src\redux-first-history\reducer.js

import { LOCATION_CHANGE } from './actions';
export function createRouterReducer(history) {
  const initialState = {
    action: history.action,
    location: history.location
  }
  return function (state = initialState, action) {
    if (action.type === LOCATION_CHANGE) {
      return { ...state, location: action.payload.location, action: action.payload.action };
    } else {
      return state;
    }
  }
}

3.6 rr6\index.js

src\redux-first-history\rr6\index.js

import React from 'react';
import { Router } from 'react-router';

export function HistoryRouter({ history, children }) {
  const [state, setState] = React.useState({
    action: history.action,
    location: history.location
  });
  React.useLayoutEffect(() => {
    history.listen(setState);
  }, [history]);
  return (
    <Router
      location={state.location}
      action={state.action}
      navigator={history}
      navigationType={state.action}
    >
      {children}
    </Router>
  )

}

标签:return,js,history,action,import,redux,first
From: https://blog.csdn.net/qq_40588441/article/details/142026378

相关文章

  • 《Head First Software Architecture》读书笔记 —— Chapter 1: software architectu
    软件架构(SoftwareArchitecture)是一个软件系统成功的基石,它不仅决定了系统的结构,也直接影响到其可扩展性、可维护性和性能表现。在这篇博客中,我们将探讨软件架构的关键维度(dimensions)、架构决策(architecturaldecisions)以及常见的架构风格(architecturalstyles),以帮助您更好......
  • Chapter4 Writing Your First Kernel Module - LKMs Part 1
    Chapter1KernelWorkspaceSetupChapter2Buildingthe5.xLinuxKernelfromSource,Part1Chapter3Buildingthe5.xLinuxKernelfromSource,Part2Chapter4WritingYourFirstKernelModule–LKMsPart1Chapter5WritingYourFirstKernelModule–......
  • first-blog
    各位师傅好,这里是saga131的博客原本打算第一个博客就介绍一下自己,在github上搭建了一个博客,但是遇到了点环境问题,便转战至博客园,用第二个博客来介绍一下自己本人是从2023年10月入门CTF和取证。社团纳新面试中,我选择了密码方向,开始了crypto之路。面试结束后,CPPUISA社团师傅让我了......
  • vue history 模式打包部署在域名的二级目录的配置指南
    1.vue-router路由的文件的配置,根据自己部署的二级目录填写123exportdefaultnewVueRouter({ mode:"history",  base:"/web",2.在vue.config.js配置文件(如果没有新建一个,项目根目录下) 注意:baseUrl从VueCLI3.3起已弃用,请使用publicPath。......
  • 057 Project Setup & First Methods
    示例index.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width,initial-scale=1.0"/><title>VueBa......
  • Writing your first Django app, part 1
    使用以下代码查看django的版本信息。$python-mdjango--version进入项目文件夹创建一个名为mysite的django项目。$django-adminstartprojectmysite会创建一个项目目录mysite/manage.pymysite/__init__.pysettings.pyurls.......
  • History API
    HistoryAPIAPIhistory.back();history.go(-1)history.forward();history.go(1)history.pushState(state,unused,url?),state:可序列化的jsobject.unused:历史原因,空字符串,url:可选,当页面恢复后有可能会加载它,但是必须同源。它会用来更新浏览器的地址栏,但是它不会加载那个......
  • css 中 nth-child、first-child、last-child 的使用(选中第一个,第几个,第几个到第几个,最
    可以配合li标签使用,选择一列中的哪些标签。 1.first-child 选择列表中的第一个标签li:first-child{color:red} 2. last-child选择列表中的最后一个标签li:last-child{color:pink} 3.nth-child(n)这里的n为数字,表示选择列表中的第n个标签例如选择第三个标签li:nth-......
  • 【Oracle点滴积累】解决ORA-06183 unable to extend index SYS.WRH$_SYSMETRIC_HISTOR
    广告位招租!知识无价,人有情,无偿分享知识,希望本条信息对你有用!今天和大家分享ORA-06183unabletoextendindexSYS.WRH$_SYSMETRIC_HISTORY_INDEXpartition错误的解决方法,本文仅供参考,谢谢!Solution:SELECTTABLESPACE_NAME,FILE_NAME,BYTES/1024/1024FILE_SIZE,AUTO......
  • 030、Vue3+TypeScript基础,路由中History和HashHistory的区别
    01、index.ts路由代码如下://创建路由并暴露出去import{createRouter,createWebHistory}from'vue-router'importHomefrom'@/view/Home.vue'importAboutfrom'@/view/About.vue'importNewsfrom'@/view/News.vue'constrouter=cr......