0.1.7 • Published 3 years ago

react-router-watcher v0.1.7

Weekly downloads
-
License
-
Repository
github
Last release
3 years ago

我们有时候会遇到这种业务场景: 进入某个页面时,我们需要验证用户是否已经登陆,是否拥有足够权限? 我们可以通过监听路由的变化来实现。但是在react下,怎么实现呢?react-router-watcher为您提供了一种方案。

演示代码(使用hook)详见https://codesandbox.io/s/aged-sun-ejpgy?file=/src/App.js

安装

npm i -S react-router-watcher

注意使用细节

无论使用以下哪种方式,都必须放在Router组件的孩子节点中。 使用之前,若不熟悉react-router,请最好先了解下react-router

API

ReactRouterWatcher

ReactRouterWatcher是一个headless风格的组件,children必须是一个函数, 该函数的形式是:

  ({
    addRouteChangeListener, // 作用是添加监听函数,接受一个监听函数作为参数
    removeRouteChangeListener // 作用是移除监听函数,接受一个监听函数作为参数
  }) => {
    // 必须返回一个react组件
    return SomeReactComponent
  }

使用方式:

<Router>
  <ReactRouterWatcher>
    {
      ({
        addRouteChangeListener, // 
        removeRouteChangeListener
      }) => {
        return <Main addRouteChangeListener={addRouteChangeListener} removeRouteChangeListener={removeRouteChangeListener}/>
      }
    }
  </ReactRouterWatcher>
<Router>

监听函数

监听函数形式如下:

/**
 *   history, match, location // 这三个参数与调用react-router的withRouter注入的参数一致
 * @param history
 * @param match
 * @param location
**/
function({history, match, location}){

}

withWatcher

withWatcher是一个高阶函数,接受一个React组件作为参数,返回一个新的react组件,这个新的组件将被自动注入addRouteChangeListener, removeRouteChangeListener两个属性 使用方式:

const Content = withWatcher(Main)

<Router>
  <Content />
</Router>

hook

const Content = () => {
  const watcher = useRouteWatcher()
  return <Main addRouteChangeListener={watcher.addListener} removeRouteChangeListener={watcher.removeListener}/>
}

<Router>
  <Content />
</Router>

准备

假设存在一个Main.js组件:

import {
  Switch,
  Route,
  useHistory
} from "react-router-dom";
import {useCallback, useEffect, useState} from 'react'
import routes from './router/router'

const Main = ({addRouteChangeListener, removeRouteChangeListener}) => {
  const history = useHistory()
  const [active, setActive] = useState('foo')
  const setBar = useCallback(() => {
    if (active === 'bar') return
    setActive('bar')
    history.push('/bar')
  }, [active, history])
  const setFoo = useCallback(() => {
    if (active === 'foo') return
    setActive('foo')
    history.push('/foo')
  }, [active, history])

  const onRouteChange = useCallback((context) => {
    console.log('onRouteChange----c--context----s--', context)
  }, [])

  useEffect(() => {
    addRouteChangeListener(onRouteChange)
    return () => removeRouteChangeListener && removeRouteChangeListener(onRouteChange)
    // return () => {
    //   removeRouteChangeListener(onRouteChange)
    // }
  }, [addRouteChangeListener, onRouteChange, removeRouteChangeListener])

  return (
    <>
      <div  style={{height: 80, display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
        <button style={active === 'foo' ? {color: 'blue', marginRight: 8} : {marginRight: 8}}  onClick={setFoo}>Foo</button>
        <button style={active === 'bar' ? {color: 'blue', marginRight: 8} : {marginRight: 8}} onClick={setBar}>Bar</button>
      </div>
      <Switch >
        {
          routes.map((item) => {
            const Component = item.component
            return (
              <Route path={item.url} key={item.url} exact >
                <Component />
              </Route>
            )
          })
        }
      </Switch>
    </>
  )
}

export default Main

案例

使用ReactRouterWatcher组件

import {
  HashRouter as Router
} from "react-router-dom";
import ReactRouterWatcher from 'react-router-watcher'
import Main from './Main'
import './App.css';

function App() {
  return (
    <Router>
      <div className="App">
        <ReactRouterWatcher>
          {
            ({addRouteChangeListener, removeRouteChangeListener}) => {
              return <Main addRouteChangeListener={addRouteChangeListener} removeRouteChangeListener={removeRouteChangeListener}/>
            }
          }
        </ReactRouterWatcher>
      </div>
    </Router>
  );
}

使用高阶函数withWatcher

import {
  HashRouter as Router
} from "react-router-dom";
import { withWatcher } from 'react-router-watcher'
import Main from './Main'
import './App.css';

const Content = withWatcher(Main)

function App() {
  return (
    <Router>
      <div className="App">
        <Content />
      </div>
    </Router>
  );
}



export default App;

使用hook

import React from 'react'
import {
  HashRouter as Router
} from "react-router-dom";
import useRouteWatcher from 'react-router-watcher/build/hook'
import Main from './Main'
import './App.css';

const Content = () => {
  const watcher = useRouteWatcher()
  return <Main addRouteChangeListener={watcher.addListener} removeRouteChangeListener={watcher.removeListener}/>
}

function App() {
  return (
    <Router>
      <div className="App">
        <Content />
      </div>
    </Router>
  );
}
0.1.7

3 years ago

0.1.6

3 years ago

0.1.5

3 years ago

0.1.3

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago