关于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

React-Hooks-的钩子够用吗

阅读此文前假设你对 React 的新特性 Hooks 有一定的了解,并能进行最基本的使用。如果还不清楚 React Hooks 是什么,也没关系,建议读完本文后再去阅读下官方关于 React Hooks 的文档今天,我们要来聊一聊 React Hooks 官方当前提供的 useXXX 到底够不够用,是否能满足我们日常的开发需求。 先说说最重要的 State: 喂喂,useState 这么核心的 API,不就是专门用于处理 State 的吗?是的,一点都没错。用过 useState 的同学应该都知道,原来的 this.setState,现在可以用 useState 的返回值中的方法 setXXX 代替,如下所示: const [ count, setCount ] = useState(0);我们来简单对比一下 class 和 Hooks 写法的差别: # get stateclass: this.state.countHooks: count# set stateclass: this.setState({count: 1})Hooks: setCount(1): 这个太简单了,了解过 React Hooks 的人都懂啊。所以你就是要给我讲这个?当然,不是啦。我问你,有没有发现少了些什么呢?原来的 this.setState(),是不是有第二个参数?这第二个参数是不是一个callback方法?这个方法是不是会在状态成功更新后调用呢? : 你这么说好像是哦,但callback我没怎么用,你能说下使用的场景吗?当然,信手拈来。 联动选择下拉框的场景,比如城市选择器。当选择了省份后,就需要去获取对应的城市列表,这个 moment 就会用到了。话不多说,先来看下 setState 的例子: class App extends React.Component { constructor() { this.state = { pId: 0 }; } onProvinceChanged(val) { this.setState({ pId: val }, () => { fetchCities(this.state.pId); }); } ...}想想如果没有callback,我们就比较难准确地在状态更新后进行一些其它的操作了 ...

October 14, 2019 · 3 min · jiezi

基于Koa和React搭建的基础项目框架

引言在个人开发过程中,因为个人主要是做前端方向的,所以在使用后端的时候更加偏向于Node这一块,目前Node比较热门的框架主要有Express和Koa两款,当然还有各大厂商基于这两款框架的二次封装框架比如Eggjs,Thinkjs。但是个人使用之后觉得并不适合个人开发,主要是框架封装太多可扩展性以及自由度不高,基础框架过于笨重即使很小的项目依赖也很多。由此引发自己弄一套基础的开发框架(可能使用框架这个词语不太合适)。目前项目主要是基于Koa和React实现。后端主要使用Koa,Knex(Sql Builder)主要支持Mysql,Redis等常见数据库,支持controller,service自动加载。前端基于React使用React hooks,React Context等较为新型的技术,加入了ant design,less等功能。 项目地址>>>https://github.com/southorange1228/so.fullstack.system目前项目处于初期开发阶段,可能存在很多问题和不足的地方,希望各位大佬能提供意见和帮助。如有任何问题请提issue或者邮件至15280970040@163.com。最后厚颜无耻的求一个star

October 14, 2019 · 1 min · jiezi

React-Hooks-你真的用对了吗

从 React Hooks 正式发布到现在,我一直在项目使用它。但是,在使用 Hooks 的过程中,我也进入了一些误区,导致写出来的代码隐藏 bug 并且难以维护。这篇文章中,我会具体分析这些问题,并总结一些好的实践,以供大家参考。 问题一:我该使用单个 state 变量还是多个 state 变量?useState 的出现,让我们可以使用多个 state 变量来保存 state,比如: const [width, setWidth] = useState(100);const [height, setHeight] = useState(100);const [left, setLeft] = useState(0);const [top, setTop] = useState(0);但同时,我们也可以像 Class 组件中的 this.state 一样,将所有的 state 放到一个 object 中,这样只需一个 state 变量即可: const [state, setState] = useState({ width: 100, height: 100, left: 0, top: 0});那么问题来了,到底用单个 state 变量还是多个 state 变量呢? 如果使用单个 state 变量,每次更新 state 时需要合并之前的 state。它不像 Class 组件的 this.setState 方法,会把更新的字段合并到 state 对象中。useState 返回的 setState 会替换原来的值: ...

October 8, 2019 · 7 min · jiezi

React-hooks实战总结

React hooks实战总结一、什么是hooks?react 于19年2月份在16.8版本中新增了hook这一特性,已经过去了半年多了,社区的各种文章解析页汗牛充栋,本文将结合自己的项目实践,对react hooks做一个全面的讲解,俗话说没吃过猪肉,还没见过猪跑吗?确实,可能大部分同学对hooks特性都有了自己的了解,但是在实际项目中使用又是另一回事了,实践出真知,这篇文章是自己对react hooks的理解,也是在上一个项目中使用react hooks的总结看着猪跑一千次,不如自己吃一次猪肉。 官方解释: hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。个人理解:让传统的函数组件function component有内部状态state的函数function。二、为什么需要hooks?在以往的react开发流程中,我们的自定义组件通常需要定义几个生命周期函数,在不同的生命周期处理各自的业务逻辑,有可能他们是重复的。解决上一个问题我们通常通过 mixins(不推荐) 或者 HOC 实现,在hooks出现之前,的确是非常好的解决途径,但是它不够好,为什么这么说呢?来看一下我们的一个具有中英文切换,主题切换同时connect一些redux 状态仓库里面的数据的全局组件alert: ```export default translate('[index,tips]')(withStyles(styles, { withTheme: true })(connect(mapStateToProps,mapDispatchToProps)(Alert)));```其实如果我们还可以将 `withTheme`也提取成一个高阶函数,那么我们的组件就将由现在的3层变成4层,实际使用的时候可能还有别的属性通过别的高阶函数添加,嵌套层级就会更深。给人明显的感觉就是不够直观。this指向问题,react绑定this有几种方式?哪一种方式性能相对来说好一些? 如果你答不上来,可以戳一下下面两个链接。 - [React事件处理](https://zh-hans.reactjs.org/docs/handling-events.html)。 - [React.js绑定this的5种方法](https://juejin.im/post/5b13c3a16fb9a01e75462a64)。hook 只能在FunctionComponent内部使用,而相比ClassComponent,传统的FunctionComponent(FC)具有更多的优势,具体体现在: - FC 容易测试,相同的输入总是有相同的输出,- FC 其实就是普通的`javascript`函数,相比于`ClassComponent`,具有潜在的更好的性能。- FC 没有生命周期函数,更容易`debug`。- FC 具有更好的可重用性。- FC 可以减少代码耦合。- [September 10th, 2018 Comments React Functional or Class Components: Everything you need to know](https://programmingwithmosh.com/react/react-functional-components/)。- [45% Faster React Functional Components, Now](https://medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f)。- `FC`有更多的优势,但是他没有生命周期,也没有自己的内部状态,我们需要复杂的状态管理机制的时候,不得不转向`ClassComponent`。 FC现有的这些问题,我们能轻松结合`hook`解决。三、useState hook 的执行过程追踪React目前官方支持的hook有三个基础Hook:useState,useEffect,useContext, 和几个额外的 Hook:useReducer,useCallback,useMemo,useRef,useImperativeHandle,useLayoutEffect,useDebugValue , 他们的作用各不相同,但是可以这么总结一下:让Function Component有状态(state),流氓不可怕,就怕流氓有文化。当我们给比较有优势的FC 插上state的翅膀之后,他就要起飞了。原来ClassComponent能干的事情他也能干起来了,加上前文分析的优势,还干的更加有声有色。这里我们使用useState做一个全面的解析, 首先我们来看一下一个简单的的计数器,点击click 按钮,state加1并渲染到页面上: ...

August 19, 2019 · 4 min · jiezi

React-Hook快速入门

Hook简介React Hooks是React 16.7.0-alpha版本推出的新特性,目的是解决React的状态共享问题。称之为状态共享可能描述的并不是很恰当,称为状态逻辑复用可能会更恰当,因为React Hooks只共享数据处理逻辑,并不会共享数据本身。在React应用开发中,状态管理是组件开发必不可少的内容。以前,为了对状态进行管理,最通常的做法是使用类组件或者直接使用redux等状态管理框架。例如: class Hook extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); }}现在,开发者可以直接使用React Hooks提供的State Hook来处理状态,针对那些已经存在的类组件,也可以使用State Hook很好地进行重构。例如: import React, { useState } from 'react';function Hook() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> );}从上面的示例可以发现,Example变成了一个函数组件,此函数组件有自己的状态,并且还可以更新自己的状态。之所以可以如此操作,是因为使用了useState,useState是react自带的一个hook函数,它的作用就是用来声明状态变量。 ...

June 11, 2019 · 2 min · jiezi

react-hooks-全面转换攻略三-全局存储解决方案

针对 react hooks 的新版本解决方案一.redux维持原方案若想要无缝使用原来的 redux,和其配套的中间件 promise,thunk,saga 等等的话可以使用 redux-react-hook github 链接 redux-react-hook 一个简单的使用例子: import {useDispatch, useMappedState} from 'redux-react-hook';export function DeleteButton({index}) { // 类似于以前 react-redux 中的 connect 函数 const mapState = useCallback( state => ({ canDelete: state.todos[index].canDelete, name: state.todos[index].name, }), [index], ); // 获取 redux 的数据 const {canDelete, name} = useMappedState(mapState); // 获取 dispatch const dispatch = useDispatch(); // button click handle const deleteTodo = useCallback( () => dispatch({ type: 'delete todo', index, }), [index], ); return ( <button disabled={!canDelete} onClick={deleteTodo}> Delete {name} </button> );}使用方法和以前一致 ...

June 5, 2019 · 3 min · jiezi

react-hook超实用的用法和技巧分析

react hook发布也已经有几个月了,相信有部分人已经开始使用了,还有些人在犹豫要不要用,可能更多人安于现状,没有要用的打算,甚至还有很多公司的react版本是15或以下的,迫于升级的难度没有使用。以我个人的观点,要不要使用react hook呢? 建议用的的人 项目react版本已经是react16了新建的项目一直对新技术保持关注,跃跃欲试的人对函数式编程爱好的人对react的componentDidMount,componentWillReceiverProps,componentDidUpdate厌烦,甚至因为重新渲染整天在头疼的人不建议用的人 对react hook极其厌恶,对react生命周期编程是非爱好的人。只要你想,没有不建议用的人,包括第一类人。这只是我个人的建议,我现在用的周期也不长,我们的项目是react 16的,并且团队里只有我自己在写ract hook。幸好react hook和生命周期编程方式是完全兼容的。 那么其实react hook的特点和优点其实也显露出来了。 1. 没有了显性的生命周期,所有渲染后的执行方法都在useEffect里面统一管理2. 函数式编程,你不需要定义constructor,render,定义class3. 某一个组件,方法需不需要渲染,重新执行完全取决于你,而且十分方便管理4. 肯定还有我没发掘的优点针对以上的特点优点我逐一说明,对于特别基础的用法我就不大篇长论了,建议参考官网的说明文档:react官网 1. 没有了显性的生命周期,所有渲染后的执行方法都在useEffect里面统一管理上代码(伪): function getData(id) { const [data, setData] = useState({}); useEffect(() => { const data = api.getData(id); setData(data); }, [id]); return <div>{data.name}</div>}这是根据id获取数据显示name的组件。因为这个id是外部传入的,在以前你需要再didMount,willReceiverProps里面去判断是否传入的和当前的不一样,然后去获取数据,但是这里就不用了。直接集成在useEffect里面。最关键的是第二个参数[id]。这个参数的意思是id变了才进入里面的方法执行,方然第一次必执行。当然我说的不全面,大致是这个意思,还有更复杂的场景,反正这种方式类似于监听id,id变了就执行,这不就是我们的最终目的吗?react以前分那么多周期其实就是处理这一件事情 2. 函数式编程,你不需要定义constructor,render,定义class这个就不用多说了吧 function heihei() { const [count, setCount] = useState(0); return ( <div> {count} <button onClick={() => setCount(count + 1)}>增加count</button> </div> )}no生命周期,no class,一切都是函数式编程 3. 某一个组件,方法需不需要渲染,重新执行完全取决于你,而且十分方便管理这里主要讲两个方法,useMemo和useCallback先看useCallback之前如果我们在render中定义了一个方法: render() { const {data} = this.state; const filter = data.filter(e => e.id !== 5); ...}那么我们知道每次render都会执行filter这个方法,其实你是不是觉得当data没变这个方法只要执行一次就好了,看看react hook怎么做的 ...

April 30, 2019 · 1 min · jiezi

react hooks 全面转换攻略(二) react本篇剩余 api

useCallback,useMemo因为这两个 api 的作用是一样的,所以我放在一起讲;语法:function useMemo<T>(factory: () => T, deps: DependencyList | undefined): T;function useCallback<T extends (…args: any[]) => any>(callback: T, deps: DependencyList): T;区别在于第一个参数,还有参数的传递,另外 useCallback 中 DependencyList 是一个必须值这两个 api 的作用基本就是缓存数据/方法使用过 react 的人都知道,在组件传递值的时候,如果 props 中某一值对象引用发生变化,就会发生重新渲染,即使前后2个对象是完全相同的;这2个参数就是为了解决这个问题,另外也有可以减轻一些方法的rerender的速度;useRef作用基本是取代 class 中的 createRef,在此不多细说useContext作用基本是取代 class 中的 Context 中 Context.Provider ,接受参数 Context,因为可能会有多层 context,所以这个参数是必须的,不然无法辨别useImperativeHandle语法:function useImperativeHandle<T, R extends T>(ref: Ref<T>|undefined, init: () => R, deps?: DependencyList): void;官网是叫 useImperativeMethods,但是我在 @types/react@17.8.7 中,是叫做 useImperativeHandle的,不过函数名还是以实际为准在官网中,他的作用是这样解释的:useImperativeMethods自定义使用ref时公开给父组件的实例值。 与往常一样,在大多数情况下应避免使用refs的命令式代码。这个 api 的使用必定伴随着 forwardRef 这个 api, 使用率基本较低;官方例子:function FancyInput(props, ref) { const inputRef = useRef(); useImperativeMethods(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} />;}FancyInput = forwardRef(FancyInput);在此示例中,呈现<FancyInput ref = {fancyInputRef} />的父组件将能够调用fancyInputRef.current.focus()。简单的说就是讲子组件中的创建方法暴露给父组件useMutationEffect签名与useEffect相同,但在更新兄弟组件之前,它在React执行其DOM突变的同一阶段同步触发。 使用它来执行自定义DOM突变。同样的 @types/react@16.8.7 没有这个函数的声明; 不过官网中 大多是告诫尽量少用此函数useLayoutEffect语法:function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void;参数基本和 useEffect 相同官方所说的效果:签名与useEffect相同,但在所有DOM突变后它会同步触发。 使用它从DOM读取布局并同步重新渲染。 在浏览器有机会绘制之前,将在useLayoutEffect内部计划的更新将同步刷新。不知道大家有没有使用过 vue,他的作用和 vue 中的 nexttick 差不多吧;在需要读取 dom 的高度,宽度的时候特别需要说到现在, api 基本已经讲完了,除了 useReducer, 我将会放在 redux 篇中讲述 ...

April 14, 2019 · 1 min · jiezi

理解 React Hooks 的 Capture Value 特性

由于刚使用 React hooks 不久,对它的脾气还拿捏不准,掉了很多次“坑”;这里的 “坑” 的意思并不是说 React hooks 的设计有问题,而是我在使用的时候,因为还没有跟上它的理念导致的一些问题。在读了一些文章后,大致是找到自己总是掉坑的原因了 —— 没理解 React Hooks 中的 Capture Value 特性。本文就以简单的示例来解释这个特性所产生的现象,对理解 Capture Value 特性做一个补充。参考文章Using the Effect Hook : 官方的 useEffect 使用教程,用例详实 ,附 useEffect - API文档精读《useEffect 完全指南》:如果你想用好 Function Component 或者 Hooks,这篇文章几乎是必读的,因为没有人能猜到什么是 Capture Value,然而不能理解这个概念,Function Component 也不能用的顺手。精读《Function VS Class 组件》 :以后在 React 中经常使用 Class 的写法,在 React Hooks 需要转换成函数式编程风格,这篇文章对比了两种写法上的差异;(这两种写法没有好坏之分,性能差距也几乎可以忽略,而且 React 会长期支持这两种写法)1、状态值为什么不是最新的?官方相关 issue:Why am I seeing stale props or state inside my function?“这个 effects 取的值怎么不是最新的?!”这个疑惑可以说是在使用 React Hooks 时经常遇到的疑问。在下列代码中,当你点击按钮 3s 后,alert 显示的数值却是 3s 前的 count 变量 —— 即无法获取最新的值,获取的值是过去某个时刻的:import React, { useState, useCallback } from “react”; import ReactDOM from “react-dom”; function Example() { const [count, setCount] = useState(0); const handleAlertClick = useCallback(()=>{ setTimeout(() => { alert(‘You clicked on: ’ + count); }, 3000) }, [count]); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> 增加 count </button> <button onClick={handleAlertClick}> 显示 count </button> </div> ); } const rootElement = document.getElementById(“root”); ReactDOM.render(<Example />, rootElement);示例代码:https://codesandbox.io/s/k5pm…具体操作步骤:当我们先点击 显示 按钮,在 3s 后(模拟耗时任务)会出现弹层在这 3s 期间快速点击 增加 count 按钮3s 后看到的弹层计数仍旧为 0.2、解释这是官方特意设置的机制,官方原文是:This prevents bugs caused by the code assuming props and state don’t change;(强行翻译一下,大概意思是:防止因 React 认为 props 或者 state 没有变更而引起的 bug)为了理解官方这么设定的意图,将上面代码稍微修改一下:去掉 显示 count 按钮增加一个 减少 count 的按钮使用 useEffect 代替 useCallback,让每次更改 count 都会弹窗…useEffect(()=>{ setTimeout(() => { alert(‘count: ’ + count); }, 3000) }, [count]); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> 增加 count </button> <button onClick={() => setCount(count - 1)}> 减少 count </button> </div> );}…我们先点击一次 增加 count,然后再紧接着点击一次 减少 count:如果不是按照官方的机制设置,那么我们看到的两次弹层显示的 count 数值都是 0 —— 很明显这不是我们想要的还好实际情况不是这样,会先显示 1,然后显示 0总结起来,这个现象其实就是文章 精读《useEffect 完全指南》 所提及的 Capture Value 特性(可以自行前往原文了解更多细节)3、扩展:如何获取即刻的 count 变量回到原来的问题,倔强如我,我就是想要在 3s 后获取的是此时此刻的 count 变量,而不是我 3s 前点击时的 count 值,该怎么操作?官方给出的解决方案是,每次改变 count 的时候,将其放在 ref 类型的变量里即可。修改一下原来的代码: const countRef = useRef(null); const handleAlertClick = useCallback( () => { setTimeout(() => { alert(“You clicked on: " + countRef.current); }, 3000); }, [count] ); return ( <div> <p>You clicked {count} times</p> <button onClick={() => { countRef.current = count + 1; setCount(count + 1); }} > 增加 count </button> <button onClick={handleAlertClick}>显示 count</button> </div> );更改过后的代码运行后,3s 后 alert 显示的 count 变量就是你页面上所见到的样子了:ref 类型的变量通常是用来存储 DOM 元素引用,但在 react hooks 中,它可以存放任何可变数据,就好比类实例属性一样,具体参考 Is there something like instance variables?这等操作,其实就是借助 ref 类型变量绕过 Capture Value 特性来达到目的。4、总结援引文章 精读《useEffect 完全指南》 中对 Capture Value 概念的解释:每次 Render 的内容都会形成一个快照并保留下来,因此当状态变更而 Rerender 时,就形成了 N 个 Render 状态,而每个 Render 状态都拥有自己固定不变的 Props 与 State。通过这个示例,相信会比较容易地理解 Capture Value 特性,并如何使用 ref 来暂时绕过它。在知道并理解这个特性后,有助于进一步熟悉了 React Hooks 的运行机制,减少掉坑的次数。这里罗列几篇文章,方便自检是否掌握了这个概念:通过 React Hooks 声明式地使用 setInterval:文章采用循序渐进的示例来解释问题。探索如何让 setInterval 和 Hooks 和谐地玩耍,为什么是这种方式,以及这种方式给你带来了什么新能力。How to get the previous props or state?: 如何获取变更前的 props 和 state ?官网提供的 useRef 来解决,也有人针对它进行了封装(How to compare oldValues and newValues on React Hooks useEffect?) ...

March 29, 2019 · 2 min · jiezi