关于react-hooks:useIoC答疑-对children属性的深入挖掘

useIoC答疑间隔上次发表 useIoC:仅一百多行代码实现前端的依赖注入 曾经过来一个多月,期间网友和我进行屡次深刻且敌对的互动。网友给我提了不少疑难和倡议,我通过一个多月的思考和实际,决定将这些疑难和倡议分享给大家。 1. 为什么不能照搬Angular的依赖注入?Angular依赖注入的对象是实例,并且要求必须提供无参数的构造函数。这个要求和 React 对 Function Component 的定义产生十分重大抵触: type FC<P = {}> = FunctionComponent<P>;interface FunctionComponent<P = {}> { (props: P, context?: any): ReactNode; propTypes?: WeakValidationMap<p> | undefined; contextTypes?: ValidationMap<any> | undefined; defaultProps?: Partial<any> | undefined; displayName?: string | undefined;}强行照搬Angular的依赖注入,须要对现有代码进行重构,把入参全副去掉或改成可选,这显然不符合实际。 其次,略微具备亿点观察力的人,很容易发现 React 规定所有函数组件返回值必须是 ReactNode 。 而 ReactNode 的定义更是万金油,位置相当于 Java 的 Object 和 Go 的 interface{} 。 type ReactNode = | ReactElement | string | number | Iterable<reactnode> | ReactPortal | boolean | null | undefined | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES];设想一下,注入的实例类型都是 ReactNode ,原来是想注入一个Input,后果注入的是Button。当你无奈限度具体的注入变量的类型时,强行应用依赖注入只会产生更重大的结果! ...

August 18, 2023 · 5 min · jiezi

关于react-hooks:React-Hooks-实现复制文本到粘贴板组件

创立一个CopyText组件,增加a标签点击时把传入的text值复制到粘贴板,并设置Copy的状态:CopyText.tsx import { Space } from 'antd';import React, { useCallback, useState } from 'react';export interface ICopyTextProps { text: string;}export const CopyText: React.FC<ICopyTextProps> = (props) => { const text = props.text; const [isCopied, setIsCopied] = useState(false); const handleClick = useCallback( () => { const input = document.createElement('input'); input.setAttribute('readonly', 'readonly'); input.setAttribute('value', text); document.body.appendChild(input); input.setSelectionRange(0, 9999); input.select(); document.execCommand('copy'); document.body.removeChild(input); setIsCopied(true); }, [text]); return ( <Space> <a style={{'wordBreak': 'keep-all'}} onClick={ handleClick } > {isCopied? 'Copied' : 'Copy'} </a> </Space> );};创立一个input元素把传入的text放入input中,最初input.setSelectionRange(0, 9999); document.execCommand('copy')进行复制。 ...

April 23, 2023 · 1 min · jiezi

关于react-hooks:React-Hooks-useEffect调用了两次

应用create-react-app脚手架创立的React前端我的项目,在函数式组件中应用useEffect加载接口数据时 发现一个奇怪的问题:刷新页面接口调用了两次!!。代码剖析useEffect(() => { const wrapper = async () => { await fetchData(); } wrapper().then(r => {});}, [param]) 在 React Hooks: useEffect() is called twice even if an empty array is used as an argument 找到了答案。 起因是开发环境应用了React严格模式,代码编译后在正式环境不会呈现这样的问题。 如果在开发环境不想呈现这种状况,能够在index.tsx中找到上面的代码: root.render( <React.StrictMode> <RouterProvider router={router}/> </React.StrictMode>);批改为: root.render( <RouterProvider router={router}/>);问题解决。

October 17, 2022 · 1 min · jiezi

关于react-hooks:Hooks的完全解决方案

一、前言React

March 18, 2022 · 1 min · jiezi

关于react-hooks:谈谈React-Hooks-与Vue30-Function-based-API的区别

hi~ 豆皮粉儿. 又见面啦~ React Hooks release 曾经有很长一段时间了,Vue3.0 也带来了 Function based API,都咱们提供了新的模式来复用和形象逻辑,那这两者有什么区别的,松宝写代码给大家带了解读。 作者: 松宝写代码一、前言React Hooks 是 React16.8 引入的新个性,反对在类组件之外应用 state、生命周期等个性。 Vue Function-based API 是 Vue3.0 最重要的 RFC (Requests for Comments),将 2.x 中与组件逻辑相干的选项以 API函数 的模式从新设计。 目录: React Hooks React Hooks是什么useState HookuseEffect HookReact Hooks 引入的起因以及设计准则React Hooks 应用准则及其背地的原理Vue3.0 Function-based API 根本用法引入的起因以及解决的问题React Hooks 与 Vue3.0 Function-based API 的比照二、React HooksReact Hooks 是什么?援用官网的一段话: 从概念上讲,React 组件更像是函数。而 Hooks 则拥抱了函数,同时也没有就义 React 的精力准则。Hooks 提供了问题的解决方案,无需学习简单的函数式或响应式编程技术。另外,Hooks 是100%向后兼容的,也是齐全可选的。 React Hooks 提供了三个根底 Hook : useState、useEffect、useContext,其余 Hooks 可参考React Hooks API。 ...

January 19, 2022 · 6 min · jiezi

关于react-hooks:ReactHooks设计动机和工作模式

一、为什么须要函数组件? 开篇咱们先来聊“Why”。React-Hooks 这个货色比拟特地,它是 React 团队在真刀真枪的 React 组件开发实际中,逐步认知到的一个改良点,这背地其实波及对类组件和函数组件两种组件模式的思考和偏重。因而,你首先得晓得,什么是类组件、什么是函数组件,并实现对这两种组件模式的辨析。 类组件(Class Component) 所谓类组件,就是基于 ES6 Class 这种写法,通过继承 React.Component 得来的 React 组件。 class DemoClass extends React.Component { // 初始化类组件的 state state = { text: "" }; // 编写生命周期办法 didMount componentDidMount() { // 省略业务逻辑 } // 编写自定义的实例办法 changeText = (newText) => { // 更新 state this.setState({ text: newText }); }; // 编写生命周期办法 render render() { return ( <div className="demoClass"> <p>{this.state.text}</p> <button onClick={this.changeText}>点我批改</button> </div> ); }}函数组件/无状态组件(Function Component/Stateless Component)函数组件顾名思义,就是以函数的状态存在的 React 组件。晚期并没有 React-Hooks 的加持,函数组件外部无奈定义和保护 state,因而它还有一个别名叫“无状态组件”。以下是一个典型的函数组件: ...

January 18, 2022 · 3 min · jiezi

关于react-hooks:react-hooks的使用记录

"对react的自带hooks进行的演绎总结"react-hooks:常见,useState、useEffect、useMemo、useRef、useCallback、useContext少见,useReducer、useImperativeHandle、useDebugValue、useTransition、useLayoutEffect useState因为函数式组件没有this与state,无奈间接批改state,因而useState是react对外裸露的一个对state操作的钩子函数。该函数可接管一个参数,是为变量的默认值,如果不写的话,变量默认为undefined。useState返回一个数组,数组的第一位是变量名,第二位是扭转该变量的函数,查看源码,会发现这个函数是一个dispatch函数(异步),所以间接查看该变量失去的是原先的值,如果要查看该变量值,配合应用useEffect去监听。扭转变量的函数有一个参数,应用的时候,间接放值类型,不可是表达式等。 const [number, setNumber] = useState(0) /* 0为初始值 */ return (<div> <span>{ number }</span> <button onClick={ ()=> { setNumber(number+1) /* 写法一 */ setNumber(number=>number + 1 ) /* 写法二 */ console.log(number) /* 这里的number是不可能即时扭转的 */ } } >num++</button> </div>)useEffect函数式组件也没有生命周期,用useEffect取代生命周期。同时对应前文所讲,useState批改的值,在这里是能够取到的,实现数据的交互。useEffect也叫副作用,顾名思义,是在渲染实现后执行。理论应用中useEffect必须填写第二个参数来应用,否则这可能会导致性能问题,比方两次渲染的数据齐全一样。第一个参数是effect函数,第二个参数是依赖项,是一个数组,如果是一个空数组,useEffect不依赖于props或state中的任何值,所以它永远都不须要反复执行,该钩子会实现componentDidMount生命周期函数的性能,即页面加载时触发一次。如果不是空数组,就要增加useState中的变量,这个变量每次发生变化就会触发useEffect,即componentDidUpdate,同时也包含componentDidMount。 const [num, setNum] = useState(1) useEffect(() => { console.log('componentDidUpdate') }, [num]) useEffect(() => { console.log('componentDidMount') }, []) return ( <> <div>{num}</div> <button onClick={() => { setNum(num + 1) }}>点击</button> </> )数组中能够放多个useState的值,每个值发生变化都会触发,理论开发中,这个依赖项数组只放一个变量。第二个参数个别状况下不要应用援用类型,因为比对的是浅比拟,援用类型的指针地址没有变动的话,进入不到useEffect中。useEffect第一个effect函数参数中还能够返回一个函数,示意解绑副作用,比方在effect函数中有个定时器,在组件销毁时须要革除定时器,此时要解绑,就能够在effect函数中返回一个函数,这个函数相当于componentWillUnmount生命周期。在应用中,从新渲染依赖项,也会先执行解绑副作用,在进行副作用,即effect函数。 ...

January 5, 2022 · 2 min · jiezi

关于react-hooks:react源码解析14手写hooks

react源码解析14.手写hooks视频解说(高效学习):进入学习往期文章:1.开篇介绍和面试题 2.react的设计理念 3.react源码架构 4.源码目录构造和调试 5.jsx&外围api 6.legacy和concurrent模式入口函数 7.Fiber架构 8.render阶段 9.diff算法 10.commit阶段 11.生命周期 12.状态更新流程 13.hooks源码 14.手写hooks 15.scheduler&Lane 16.concurrent模式 17.context 18事件零碎 19.手写迷你版react 20.总结&第一章的面试题解答 最要害的是要了解hook队列和update队列的指针指向和updateQueue的更新计算,具体见视频解说 import React from "react";import ReactDOM from "react-dom";let workInProgressHook;//当前工作中的hooklet isMount = true;//是否时mount时const fiber = {//fiber节点 memoizedState: null,//hook链表 stateNode: App//dom};const Dispatcher = (() => {//Dispatcher对象 function mountWorkInProgressHook() {//mount时调用 const hook = {//构建hook queue: {//更新队列 pending: null//未执行的update队列 }, memoizedState: null,//以后state next: null//下一个hook }; if (!fiber.memoizedState) { fiber.memoizedState = hook;//第一个hook的话间接赋值给fiber.memoizedState } else { workInProgressHook.next = hook;//不是第一个的话就加在上一个hook的前面,造成链表 } workInProgressHook = hook;//记录当前工作的hook return workInProgressHook; } function updateWorkInProgressHook() {//update时调用 let curHook = workInProgressHook; workInProgressHook = workInProgressHook.next;//下一个hook return curHook; } function useState(initialState) { let hook; if (isMount) { hook = mountWorkInProgressHook(); hook.memoizedState = initialState;//初始状态 } else { hook = updateWorkInProgressHook(); } let baseState = hook.memoizedState;//初始状态 if (hook.queue.pending) { let firstUpdate = hook.queue.pending.next;//第一个update do { const action = firstUpdate.action; baseState = action(baseState); firstUpdate = firstUpdate.next;//循环update链表 } while (firstUpdate !== hook.queue.pending);//通过update的action计算state hook.queue.pending = null;//重置update链表 } hook.memoizedState = baseState;//赋值新的state return [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回 } return { useState };})();function dispatchAction(queue, action) {//触发更新 const update = {//构建update action, next: null }; if (queue.pending === null) { update.next = update;//update的环状链表 } else { update.next = queue.pending.next;//新的update的next指向前一个update queue.pending.next = update;//前一个update的next指向新的update } queue.pending = update;//更新queue.pending isMount = false;//标记mount完结 workInProgressHook = fiber.memoizedState;//更新workInProgressHook schedule();//调度更新}function App() { let [count, setCount] = Dispatcher.useState(1); let [age, setAge] = Dispatcher.useState(10); return ( <> <p>Clicked {count} times</p> <button onClick={() => setCount(() => count + 1)}> Add count</button> <p>Age is {age}</p> <button onClick={() => setAge(() => age + 1)}> Add age</button> </> );}function schedule() { ReactDOM.render(<App />, document.querySelector("#root"));}schedule();

December 4, 2021 · 2 min · jiezi

关于react-hooks:MaterialUI-使用反馈

最近工作中须要开发手机端H5页面,没有应用相熟的 React + Antd-mobile, React + Taro UI,Vue + uView ,而是应用了 React + Material-UI做了一次全新的尝试。而且正好最近React-router/React-router-dom 强行用 hooks模式 迭代了一个大版本@6; 目标: 看腻了antd的中台款式,体验一下Material的【暗黑模式】以及可配置的【调色板】。 React 相干版本信息: "react": "^17.0.2", "react-dom": "^17.0.2", "react-redux": "^7.2.6", "react-router": "^6.0.2", "react-router-dom": "^6.0.2",Material-UI 相干版本信息: "@emotion/react": "^11.6.0", "@emotion/styled": "^11.6.0", "@material-ui/core": "^5.0.0-beta.5", "@material-ui/styles": "^4.11.4", "@mui/icons-material": "^5.1.1", "@mui/lab": "^5.0.0-alpha.56", "@mui/material": "^5.1.1", 应用组件有:Typography Button Radio Select Switch TextField Badge List Table Tooltip Alert Dialog Progress Accordion Card Paper Menu Pagination Grid Modal Date Range Picker... ...

December 2, 2021 · 9 min · jiezi

关于react-hooks:最陌生的hooks-useImperativeHandle

预计都比拟相熟这些HOOKS了吧:useState, useEffect, useContext, useMemo。但我当第一次看到useImperativeHandle时,一脸懵逼(这是什么鬼货色~~~)。 一、是什么?React官网对useImperativeHandle介绍也比拟简短。总结一句话就是:子组件利用useImperativeHandle能够让父组件输入任意数据。 // FancyInput组件作为子组件const FancyInput = React.forwardRef(function FancyInput(props, ref) { const inputRef = useRef(); // 命令式的给`ref.current`赋值个对象 useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus() } })); return <input ref={inputRef} ... />})// Example组件作为父组件function Example() { const fancyInputRef = useRef() const focus = () => { fancyInputRef.current.focus() } return ( <> <FancyInput ref={fancyInputRef} /> </> )}二、怎么用?2.1 语法useImperativeHandle(ref, createHandle, [deps])ref须要被赋值的ref对象。createHandle:createHandle函数的返回值作为ref.current的值。[deps]依赖数组,依赖发生变化会从新执行createHandle函数。2.2 进阶:什么时候执行createHandle函数?测试发现和useLayoutEffect执行机会统一。批改下组件FancyInput内容: const FancyInput = React.forwardRef(function FancyInput(props, ref) { const inputRef = useRef(); console.log('render 1') useLayoutEffect(() => { console.log('useEffect1', ref) }) useImperativeHandle(ref, function() { debugger console.log('useImperativeHandle') return { focus: () => { inputRef.current.focus(); } } }) useLayoutEffect(() => { console.log('useEffect2', ref); }) console.log('render 2') return <input ref={inputRef} placeholder="FancyInput"/>;})看看控制台输入发现createHandle函数的执行机会和useLayoutEffect统一,这样就保障了在任意地位的useEffect里都能拿到最新的ref.current的值。 ...

September 29, 2021 · 1 min · jiezi

关于react-hooks:react-hooks轮播图

// 用于记录轮播图的以后激活序号 const [activeId, setActiveId] = useState(0);// 用于管制轮播图的位移const [position, setPosition] = useState(0);// 用于管制自动播放const [autoPlayFlag, setAutoPlayFlag] = useState(true);let timer = useRef()const runTimer = () => { timer.current = setInterval(() => { // 这时候的num因为闭包的起因,始终是0,所以这里不能间接用setActiveId(activeId-1) setActiveId(n => { if (n > 3) { return 0 } else { return n+1 } }) },5000)}useEffect(() => { runTimer() return () => { // 组件销毁时,革除定时器 if (timer.current) clearInterval(timer.current) }},[autoPlayFlag])const handleClick = (idx:number) => { clearInterval(timer.current) setActiveId(idx)}useEffect(() => { if (!timer.current) { runTimer() } setPosition(721 * activeId)},[activeId])const slides = suitableList.map((slideContent:any, i) => <div key={`customize_suit_${slideContent.id}_${i}`} className={sty.swiperImgBox}> <div className={sty.swiperImg} style={{background: `url(${slideContent.url}) no-repeat center / cover`}}> </div> </div>);// 款式不贴了,父级宽度100%,inner宽度3605px(721乘以5)return <div className={sty.suitableCntBoxRight}> <div className={sty.suitableCntBoxRightInner} style={{left: `-${position}px`}}> {slides} </div> </div>

August 27, 2021 · 1 min · jiezi

关于react-hooks:解密React-state-hook

先看个问题,上面组件中如果点击3次组件Counter的“setCounter”按钮,控制台输入是什么? function Counter() { const [counter, setCounter] = useState(1); console.log('Counter.render', counter); return ( <> <Display counter={counter}/> <button onClick={() => setCounter(2)}>setCounter</button> </> )}function Display({ counter }) { console.log('Display.render', counter); return <p>{counter}</p>}...正确的答案是: 第一次点击“setCounter”按钮,state的值变成2触发一次re-render;即输入: Counter.render 2Display.render 2第二次点击“setCounter”按钮,尽管state的值没有变,但也触发了一次组件Counter re-render,然而没有触发组件Display re-render;即输入: Counter.render 2第三次点击“setCounter”按钮,state没有变,也没有触发re-render。一、更新队列1.1 什么是更新队列其实每个state hook都关联一个更新队列。每次调用setState/dispatch函数时,React并不会立刻执行state的更新函数,而是把更新函数插入更新队列里,并通知React须要安顿一次re-render。举个栗子: function Counter() { const [counter, setCounter] = useState(0); console.log('Counter.render', counter); return ( <> <Display counter={counter}/> <button onClick={() => setCounter(counter + 1)}>Add</button> <button onClick={() => { console.log('Click event begin'); setCounter(() => { console.log('update 1'); return 1; }); setCounter(() => { console.log('update 2'); return 2; }); console.log('Click event end'); }}>setCounter</button> </> )}先点击下"Add"按钮(前面解释起因),再点击“setCounter”按钮看下输入: ...

August 9, 2021 · 4 min · jiezi

关于react-hooks:不满意社区的轮子我们自创了一套-React-Hooks-风格的数据加载方案

作者:leancloud 李叶 React Hooks 自公布以来,因其简略合乎直觉的 API 与灵便的组合能力,很快就在 LeanCloud 控制台的重构我的项目中失去了宽泛应用。对于「从服务端加载组件所需数据」这一需要,因为最开始的需要比较简单,咱们没有引入第三方库而是本人封装了一些 API 来实现。随着重构的进行,这些 API 逐步演变并造成了一套绝对残缺的计划。在比照了社区中其余的一些热门「加载数据 Hook 库」之后,咱们发现社区中很少有对相似的设计方案的探讨。这篇文章将介绍这个计划是如何演进,以及它是如何以一种更加合乎「Hook」设计格调的形式来满足咱们遇到的各种需要的。 计划的源码凋谢在了 GitHub 上:https://github.com/leancloud/use-resource 内容分为三个局部: 外围办法(createResourceHook)扩大性能特点与劣势外围办法(createResourceHook)咱们的摸索开始于最简略的需要:应用 hook 加载一个 REST API。在这个场景中,咱们关注的状态有三个:(胜利的)后果、异样以及是否正在加载。因而在设计中,咱们的代码看起来应该是这个样子的: const Clock = () => { const [data, { error, loading }] = useFetch(['<https://worldtimeapi.org/api/timezone/etc/utc>']); return ( <div> {loading && 'Loading...'} {error && error.message} {data && data.datetime} </div> );};useFetch 的第一个参数是 fetch 的参数列表,返回三个状态 data、error 与 loading。因为 data 简直是肯定会用到的,同时为了方便使用的中央对其重命名,咱们将其独自作为 tuple 的第一个元素返回。 这篇文章接下来探讨的所有性能与扩大都将基于这个useFetch hook。useFetch 是由一个叫做 createResourceHook 的办法创立的。createResourceHook 是这个计划中最外围的 API,它会将一个申请数据的办法(比方 fetch)转换为一个 hook,其定义如下: ...

December 10, 2020 · 4 min · jiezi

关于react-hooks:React-Hook丨这两个hook加ts如虎添翼

 You Might Not Need Redux. —— Dan Abramov然而咱们能够用 useReducer 和 useContext ~ 后面说的话:useContext 能够实现状态共享,useReducer 能够实现犹如 redux 状态管理器 dispatch 的性能 。这样一来,咱们就能够拿这两个hook来实现一个简略的状态管理器了。如果再退出ts呢,咱们能够想到的是本人定义的诸多 type,通过ts加编辑器的反对,在咱们眼前出现的那种愉悦感 ~ 在我的项目中,咱们可能会有多个状态须要共享,咱们可能会在登录后异步申请获取用户信息,而后在其余页面会用到这个用户信息... 。 那就让咱们就用这两个hook举个例子吧:( 这两个hook还不理解的小伙伴,能够看上一篇文章介绍,点我点我 ) 实现异步获取用户信息的相干文件userInfo/index.declare.ts export interface IState { id?: string; name?: string; isFetching?: boolean; failure?: boolean; message?: string;}type TType = | "ASYNC_SET_USER_INFO" | "FETCHING_START" | "FETCHING_DONE" | "FETCHING_FAILURE";export interface IAction { type: TType; payload?: IState;}这个文件这里把它提取进去,申明了根本的 state 、type的束缚与action,参数用 payload 来接管 userInfo/index.tsx import React, { useReducer, createContext, useContext } from "react";import { IState, IAction } from "./index.declare";// 初始化状态const initialState: IState = { id: "", name: "", isFetching: false, failure: false, message: ""};// 创立一个 context,并初始化值const context: React.Context<{ state: IState; dispatch?: React.Dispatch<IAction>;}> = createContext({ state: initialState});// reducerconst reducer: React.Reducer<IState, IAction> = ( state, { type, payload }): IState => { switch (type) { case "ASYNC_SET_USER_INFO": { const { id, name, message } = payload!; return { ...state, id, name, message }; } case "FETCHING_START": { return { ...state, failure: false, isFetching: true }; } case "FETCHING_DONE": { return { ...state, isFetching: false }; } case "FETCHING_FAILURE": { return { id: "", name: "", failure: true, message: payload?.message }; } default: throw new Error(); }};/** * mock:模仿了申请接口的异步期待 */const request = (id: string): Promise<any> => { return new Promise((resolve, reject) => { setTimeout(() => { if (id === "998") { resolve({ id: "998", name: "liming", message: "获取用户胜利" }); } else { reject(`找不到id为${id}的用户`); } }, 1000); });};/** * dispatch 异步/同步 高阶函数 */const dispatchHO = (dispatch: React.Dispatch<IAction>) => { return async ({ type, payload }: IAction) => { if (type.indexOf("ASYNC") !== -1) { dispatch({ type: "FETCHING_START" }); try { const { id, name, message } = await request(payload!.id!); dispatch({ type, payload: { id, name, message } }); } catch (err) { dispatch({ type: "FETCHING_FAILURE", payload: { message: err } }); } dispatch({ type: "FETCHING_DONE" }); } else { dispatch({ type, payload }); } };};/** * ProviderHOC 高阶组件 */export const ProviderHOC = (WrappedComponent: React.FC) => { const Comp: React.FC = (props) => { const [state, dispatch] = useReducer(reducer, initialState); return ( <context.Provider value={{ state, dispatch: dispatchHO(dispatch) }}> <WrappedComponent {...props} /> </context.Provider> ); }; return Comp;};/** * 封装 useContext */export const useContextAlias = () => { const { state, dispatch } = useContext(context); return [state, dispatch] as [IState, React.Dispatch<IAction>];};解释: ...

November 20, 2020 · 3 min · jiezi

关于react-hooks:React-Hook丨用好这9个钩子所向披靡

Hook 进去后,置信很多小伙伴都本人蠢蠢欲动,对于喜爱用react的,又喜爱Hook的,本篇文章将会与你一起玩转Hook。 文章篇幅有一丢丢长,但请急躁品它 ~ 钩子函数:某个阶段触发的回调函数。例:vue的生命周期函数就是钩子函数工欲善其事,必先利其器让咱们先深刻理解react内置的这几个钩子这里咱们简略给几个钩子贴上标签 useState【保护状态】useEffect【实现副作用操作】useContext【应用共享状态】useReducer【相似redux】useCallback【缓存函数】useMemo【缓存值】useRef【拜访DOM】useImperativeHandle【应用子组件裸露的值/办法】useLayoutEffect【实现副作用操作,会阻塞浏览器绘制】接下来,咱们来针对这9个钩子一一深刻理解useState一般更新 / 函数式更新 state const Index = () => { const [count, setCount] = useState(0); const [obj, setObj] = useState({ id: 1 }); return ( <> {/* 一般更新 */} <div>count:{count}</div> <button onClick={() => setCount(count + 1)}>add</button> {/* 函数式更新 */} <div>obj:{JSON.stringify(obj)}</div> <button onClick={() => setObj((prevObj) => ({ ...prevObj, ...{ id: 2, name: "张三" } })) } > merge </button> </> );};useEffectuseEffet 咱们能够了解成它替换了componentDidMount, componentDidUpdate, componentWillUnmount 这三个生命周期,然而它的性能还更弱小。 ...

November 17, 2020 · 5 min · jiezi

关于react-hooks:Function组件Hooks-vs-Class组件

前言对于Hook的定义官网文档是这么说的:Hook 是 React 16.8 的新增个性。它能够让你在不编写 class 的状况下应用 state 以及其余的 React 个性。简略来说,就是可能通过function组件+hooks来实现class组件的工作。所以咱们未免要拿class和hooks进行比照。 function组件每次渲染都会有独立props/state,而class组件总是会通过this拿到最新的props/stateclass组件实例化一次,应用到的props/state都是通过this去获取,而this是可变的(mutable),所以在生命周期中所拿到的都是最新的props/state。 function组件每次渲染都会执行一次,每次渲染都有这次渲染所对应的独立的props/state。 所以在一些非凡状况下,class组件就会有谬误的体现,比方点击一个延时输入状态的按钮,在延时输入后果之前去更改状态,最终后果总是最新批改的状态,而不是点击延时按钮时的状态。就像Dan的文章函数式组件与类组件有何不同?中所举的例子。 function组件逻辑聚合,而class组件逻辑扩散下面一点提到的两者的异同点并没有波及到hooks,只是单纯的function组件和class组件之间的区别,而当初要比照退出了hook之后的function组件。 class组件中的生命周期绝大部分的工作是在不同的时刻去解决一些副作用,而function也须要一种机制去解决组件交互过程中的副作用,这就是useEffect。 class组件中可能会将同一个性能的逻辑拆分到不同的生命周期中,比方会在componentWillUnMount中去卸载定时器再比方在每次传入的props发生变化时去执行副作用就须要在componentDidMount和componentDidUpdate两个生命周期中去写对应的逻辑而在function组件中,下面同样的逻辑应用useEffect去解决副作用就会使得逻辑非常聚合,不会将同一模块的逻辑散落到不同的中央。 function组件逻辑复用简略,而class组件逻辑复用艰难在class组件中,逻辑复用的计划包含HOC和render props,然而这类计划都是将逻辑封装到一个形象层的组件中,在应用多个复用逻辑时会造成形象层组件的“嵌套天堂”。 例如一个组件须要复用鼠标地位逻辑和window size 变动的逻辑,让咱们来比照下HOC、render props和hooks之间的逻辑复用 1. render propsReact DevTools 中对应的组件 2. HOCReact DevTools 中对应的组件 3. hooksReact DevTools 中对应的组件 能够看出HOC和render props都会扭转原先的组件构造,而hook能够使你在无需批改组件构造的状况下复用状态逻辑,并且在一个组件应用多个复用逻辑的状况下,hooks清晰简洁的逻辑提取和应用形式更能体现出劣势。 参考地址: https://www.zhihu.com/questio...https://zh-hans.reactjs.org/d...

September 10, 2020 · 1 min · jiezi

关于react-hooks:重学react

一、react根底react类组件负责逻辑管制,比方批改数据 ==> vdomReactDOM负责渲染,vdom ==> dombabel-loader能够转化 jsx ==> vdom<h1>react真帅</h1> ==> React.createElement('h1','react真帅')

August 8, 2020 · 1 min · jiezi

关于react-hooks:重学react

一、react根底react类组件负责逻辑管制,比方批改数据 ==> vdomReactDOM负责渲染,vdom ==> dombabel-loader能够转化 jsx ==> vdom<h1>react真帅</h1> ==> React.createElement('h1','react真帅')

August 8, 2020 · 1 min · jiezi