react梳理之Hooks(二)

昨天没有梳理完的今天接着梳理

  • userContext()
  • userReducer()
  • useMemo()
  • useCallback()
4. userContext
  1. userContext的作用
    userContext就是context的接收方式不同,在前边的react传值梳理中我们就已经说过,有一种方式就是context传值,context在react中就如字面含义一样,是我们react使用中的一种容器,通过React.createContext来创建一个容器ContextObj,容器作为标签ContextObj.Provider包裹我们要传递值的生产者,那我们内部的所有消费者,也就是子组件,都可以通过ContextObj.Consumer来包裹,然后通过箭头函数的模式获取到参数value,内部也都可以正常使用整个value的值,但是无疑这种方法是繁琐的,那么我们函数式组件中的跨级传输救星来了,就是userContext,userContext可以直接获取到我们所需的值,让消费者解放出来,不再需要标签包裹就能获取到相应的参数
  2. userContext使用
import React,{ useContext } from 'react'
const Ceshi = () => {
  const AppContext = React.createContext({})
  const A =() => {
    const { name } = useContext(AppContext)
    return (
        <p>我是A组件的名字{name}<span>我是A的子组件{name}</span></p>
    )
}
const B =() => {
  const { name } = useContext(AppContext)
  return (
      <p>我是B组件的名字{name}</p>
  )
}
  return (
    <AppContext.Provider value={{name: 'hook测试'}}>
    <A/>
    <B/>
    </AppContext.Provider>
  )
}
export default Ceshi 

如果有不太了解的可以看我前边梳理的react传值,那里有说明如何使用context传值方式,有了userContext也只是让我们获取传值获取的更加便捷,代码更加的简洁,但是userContext也是有缺点的,或者说context传值方式也是有缺点的,就是会使代码的复用性变得更差,为什么这样说,因为我们就算不用标签包裹的方式之后,还是需要组件和父组件的传值进行逐个对应的,不然我们的子组件被抽离以后需要的传值我们就无法获取了,就算我们给子组件的获取传值做了兼容,也会固定化父组件的传值方式

5. userReducer
  1. userReducer的作用
    我们之前梳理的rudex我们可以看一下,我们也可以在这里简单说一下,redux是react的一种状态共享方式,内部有一个很重要的概念就是reducer,reducer就是作为我们action,也就是通知处理方案的函数,这个函数会接收到两个值,一个是state,也就是旧时的状态,另一个就是我们的action通知,且可以拿到我们的dispatch通知时候传递过来的type和传递的value,这两个值一个可以让我们做出判断走哪里的修改逻辑,另一个可以让我们获取到要修改替换的属性的新值,从而达到对旧值更改的目的,当然了我们的userReducer也是从rudex中吸取的经验所产生的,只不过userReducer是直接可以在hooks中进行使用的,不用引入新的rudex和rudex-react,内置hooks

  2. userReducer的使用

import React,{useReducer} from 'react'

const AddCount = () => {
	const reducer = (state, action) =>  {
 		if(action.type === 'add'){
  			return {
  				...state,
  				count: state.count +1,
  			}
		}else {
   			return state
		}
	}
	const addcount = () => { 
  		dispatch({
    		type: 'add'
  		})
	}
	const [state, dispatch] = useReducer(reducer, {count: 0})
	return (
		<>
			<p>{state.count}</p>
			<button onClick={addcount}>count++</button>
		</>
	)
}
export default AddCount

从上边的代码我们可以看到,我们把整个的代码逻辑抽离了出来,不管是状态还是改变状态的函数,都已经被我们改变,我们没有再用到useState去生成变量且在dom逻辑中使用,而是用了外部生成变量且外部dispatch通知修改变量这样的方式,其实从这里我们看不到优势,而且我们的useReducer每次调用都会产生不同的state和dispatch,这样我们在子组件中使用的时候,就无法和redux一样进行状态的集中管理了,这就要看我们上边的useContext了,这也是为什么我在前一个章节说他们是一对儿的原因

  1. 与useContext配合使用
import React from 'react';
import './style.css';
//createContext函数内可以传递一个默认的共享数据,我们用不到所以传
const ContextObj = React.createContext();

function AAA() {
	const { dispatch} = useContext(AppContext)
    return (
          <div>
            我是组件1我除了自己的逻辑,我还可以更改组件2获取的值
            <button
              onClick={() => {
                  	dispatch({
    					type: 'change',
    					name: 333
  					})
              }}
            >
              点击改变值
            </button>
          </div>
    );
}

function BBB()  {
	const { name } = useContext(AppContext)
    return (
    	<div>我是组件2获取到的值:{name}</div>
    );
}

function App() {
	const AppContext = React.createContext({})
	const reducer = (state, action) =>  {
 		if(action.type === 'change'){
  			return {
  				...state,
  				name: action.name,
  			}
		}else {
   			return state
		}
	}
	const [state, dispatch] = useReducer(reducer, {name: 222})
    return (
      <ContextObj.Provider
        value={{name, dispatch}}
      >
        <div>
          <AAA />
          <BBB />
        </div>
      </ContextObj.Provider>
    );
}

export default App;

这个是我拿我之前做的context传值方式中的例子进行改造的一个,如果想要了解清楚,建议可以对比着看传值梳理,我们从例子中可以看到,我们context做了什么,把state和dispacth进行了传值共享,这样的话我们的每个子组件都可以通过useContext来获取到state和dispatch,这样我们在任何的子组件中都可以访问到我们父组件中useReducer创建的状态和状态管理,也就达到了我们一系列组件和子组件公用一套状态的目的,要记住React.createContext是必不可少的东西,虽然我们用useContext接收但是我们传递还是用react原本的方法去传递

6. useMemo

我们都知道react是自动进行更新且会自动更新所有的子组件的,我们的useMemo需要我们从头说起,从最开始的缓存说起

  1. PureComponent
    我们之前没有说过这个,这次趁机说一下这个PureComponent,这个的用法就是在我们进行类组件的创建的时候,不再从react.Component来继承,而是从PureComponent来继承,如此一来我们的类组件会自动多一个方法,就是每次更新的时候把props和state做一次浅比较,看一看我们使用的组件需不需要做出更新,当然了我们之前也说过,用shouldComponentUpdate可以自定义比较方法,根据我们自定义的比较返回true或者false来表明是否需要更新render,但是如果我们用PureComponent就可以自己进行浅比较
import React, { PureComponent } from 'react';
class IndexPage extends PureComponent{
  constructor() {
    super();
    this.state = {
      isShow: 1
    };
  }
  render() {
    return (
      <div>
        <div>{this.state.isShow}</div>
      </div>
    );
  }
}
  1. React.memo
    react的HOC(高阶组件),我们可以通过这个高阶组件进行缓存的处理,每次我们的父组件更新的时候,用这个高阶组件包装导出的组件都会进行对比方法的调用,当然了对比方法就是我们在进行高阶组件包装时候传入的方法,且注意,react.memo就是为了我们的函数式组件的缓存出现的,所以我们函数式组件很适合用这个高阶组件
import React, { memo } from 'react';
function MyComponent(props) {
	return <div>{props.name}<div>
}
function areEqual(prevProps, nextProps) {
//做旧props和新props的对比
}
export default memo(MyComponent, areEqual);
  1. useMemo
    useMemo为我们提供的是更加简便的用法以及更加只能的监控数据是否改变,我们可以把我们依赖的值细分且传入useMemo包裹之后的组件中的第二个数组参数中,这样useMemo就会替我们做对比,来判断是否要更新组件,依赖的传入方式使我们开发更加的顺畅,不用每次都写那么多的比较逻辑,重复且复杂
import React, { useMemo } from 'react';

function MyComponent(props) {
    return useMemo(() => {
        return <div>
            <p>number is : {props.number}</p>
        </div>
    }, [props.number]);
}
export default MyComponent;
7. useCallback
  1. useCallback的作用
    useCallback与上边讲的几个缓存的方式不同,useCallback做的是函数的缓存,为什么要做函数的缓存,要知道我们在整个函数组件中,不管任何东西做出改变,整个的函数一定意义上是要重新走一遍的,也就意味着我们的函数每次都是进行了一次重新定义,js中的对象,进行两次完全一样的创建,进行全等对比,都是不相等的,为什么,因为对象是引用变量,那么我们就知道函数也是引用变量,每次传递给子组件的函数都是作用一样,但是引用是不一样的,这就会导致我们传递的参数实际上是在每次父组件更新时都在发生改变的,我们就可以对函数进行缓存,这样每次组件刷新生成的函数都是同一个引用,传递的时候子组件接收到的也就是同一个函数了
import React, { memo, useCallback, useState } from 'react'
function PageA (props) {
  const { onClick, children } = props
  return <div onClick={onClick}>{children}</div>
}
function PageB ({ onClick, name }) {
  return <div onClick={onClick}>{name}</div>
}
const PageC = memo(PageB)
function UseCallback() {
  const [a, setA] = useState(0)
  const [b, setB] = useState(0)
  const handleClick1 = () => {
    setA(a + 1)
  }
  const handleClick2 = useCallback(() => {
    setB(b + 1)
  }, [b])
  return (
    <>
      <PageA onClick={handleClick1}>{a}</PageA>
      <PageC onClick={handleClick2} name={b} />
    </>
  )
}
export default UseCallback

从以上代码我们可以看出,我们使用useCallback的时候跟memo进行搭配使用,因为memo不传递第二个函数的时候,进行比较就是选择性的浅比较,那么我们的状态浅比较并没有更改的情况下,我们传递的方法如果也是完全相同的,那么我们的子组件就不会进行更新了,反之我们如果没有用UseCallback,那我们的传递的方法每次都在进行改变,其实还是进行更新的,所以,这也是一对儿

总结: 其实react的函数式组件中的hooks都是不太复杂的,如果不了解原理只说使用的话,最简单的例子就可以说明清楚,我们加上我们自己的文字陈述之后,能更加容易的理解且记住我们hooks的具体用法,一切皆有定式,所以我们拿来就用,其实也没错啦

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Hooks 是 React 16.8 版本引入的新特性,它允许我们在无需编写类组件的情况下使用状态和其他 React 特性。对于级路由的实现,我们可以使用 React Router 来管理路由。 首先,确保你已经安装了 `react-router-dom` 包。接下来,你需要创建一个包含级路由的组件。这个组件将作为父级路由的容器,并且可以渲染其他子组件。 首先,在你的项目导入所需的依赖: ```javascript import React from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; ``` 然后,创建一个包含级路由的组件: ```javascript const SubRoutesComponent = () => { return ( <Router> <Switch> <Route exact path="/subroute1"> {/* 渲染子路由1的组件 */} </Route> <Route exact path="/subroute2"> {/* 渲染子路由2的组件 */} </Route> <Route exact path="/subroute3"> {/* 渲染子路由3的组件 */} </Route> </Switch> </Router> ); }; ``` 在上面的示例,我们创建了三个子路由,分别是 `/subroute1`、`/subroute2` 和 `/subroute3`。你可以根据自己的需求添加更多的子路由。 最后,在你的应用程序使用该组件: ```javascript const App = () => { return ( <Router> <Switch> <Route exact path="/"> {/* 渲染主页组件 */} </Route> <Route path="/subroutes"> <SubRoutesComponent /> </Route> </Switch> </Router> ); }; ``` 在上面的示例,我们将 `SubRoutesComponent` 组件作为 `/subroutes` 路径的子路由引入。这意味着当访问 `/subroutes` 时,将渲染 `SubRoutesComponent` 组件,并且根据子路由的路径进行匹配和渲染。 这样就实现了在 React 使用级路由。你可以根据自己的需求修改和扩展这个示例来满足你的项目要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值