Jsonz
Jsonz
看[7.3 跨组件状态共享(Provider)](https://book.flutterchina.club/chapter7/provider.html)的时候发现跑不了,来跑代码,拉下来之后发现项目里面好像缺少实现 `ChangeNotifier` 类 Undefined class 'ChangeNotifier'. Try changing the name to the name of an existing class, or creating a class with the name 'ChangeNotifier'. 基于这个commit的最新代码 [commit](https://github.com/wendux/flutter_in_action_source_code/commit/55cba13eaa33e51ca16c662a18dff551359f5a75)
这篇讲一下目前接触最多的Hook: `useEffect`,期间也会穿插一些用到的Hooks。 一般我们会用它来请求数据或者模拟生命周期里面的一些操作,对于模拟生命周期的操作,我们之前有讲过,可以参考[第二篇 ](./7) 这里我我们主要以CNode的接口为例子写个demo,获取某个主题下面的帖子列表并展示出来 ---- ### 基本的Demo 常规操作,在CDM里面调用接口,然后setState渲染出来,最简单的demo就写好了 [live demo1 下拉框:基础列表](https://codesandbox.io/s/eloquent-keldysh-g3nnh?fontsize=14) ![hook3_demo1](https://user-images.githubusercontent.com/11730463/62954252-a1d80d80-be21-11e9-92fb-6e90bc5c51bb.png) 这里扯个点,useEffect 不可以是async的形式,即`useEffect(async () => {})`。 因为useEffect会将返回的函数作为清除时调用,而async默认就会返回一个Promise,这明显不是我们想要的结果,所以如果这么写React会给你一个警告。 --------- ### 参数变换 但是一般我们的业务都不是这么简单,最起码有多个主题,你好歹得给别人切换一下主题吧? 如果是Class,我们一般会有一个下拉框,然后用户选择的时候`setState(type)`去改变用户当前选择的主题,再在`CDU(ComponentDidUpdate)`里面判断`this.state.type !== prevState.type`去调接口更新数据 如果按着这样翻译到Hooks的话,就是`useEffect(() => 调接口, [type])`,但是我不建议大家还是以Class的思维来写Hooks,这样每次写一个功能首先想到的是Class怎么实现,然后再想着怎么翻译成Hooks,吃力不讨好。...
React16 更新了新的 Context API,在这之前官方一直都不被官方提倡使用。 # Context API 截至 Reaact 16.6.3,共提供了四组 api: `React.createContext`、`ReactContext.Provider`、`Class.contextType`、`ReactContext.Consumer`。 **下面我们把提供 context 的组件叫为 provider(提供者),把用到 context 组件叫做 consum(消费者)** ## React.createContext(defaultValue) [源码地址](https://github.com/jsonz1993/react/blob/jsonz-v16.6.3/packages/react/src/ReactContext.js#L17) 该方法传入一个初始值/默认值,创建一个 `ReactContext`。 ```javascript // 基本的data const themes =...
第二篇我们先来介绍这次的主角,几个比较常用的Hooks,本篇只涉及到几个常用的:useState, useEffect, useRef, useReducer useState ---- 可以理解为是ClassC中的setState,他也是官方一直宣传的赋予Hooks state的方法。 但是使用上最大的不同就是他每次`setState`不会自动帮你做merge,而是全替换,所以是自己封装一个方法,还是每次都用函数式更新,还是直接用`useReduce`(下面会讲到)看个人喜欢 ```javascript import React, { useState } from 'react' const App = () => { const [state, setState] = useState({ name: 'jsonz',...
>好久没有水文了,接下来就写几篇关于React Function Component和 Hooks 的,当做最近工作的总结 在讲`React Hook`之前,我们先来思考一下,Function Component和class Component有什么区别 _在线预览本来想用jsRun,注册完之后发现官方支持引进的库版本都特别老,比如react只支持0.x,相反codesandbox默认支持react就很舒服了_ 这是一个简单的Demo 点击按钮会把延迟三秒之后输入框的值给打印出来,大家先把玩把玩,看能不能试出FunC和ClassC两者的区别 [live demo](https://codesandbox.io/s/reverent-carson-ggbqq?fontsize=14) ![hooks_demo1](https://user-images.githubusercontent.com/11730463/62720472-acb72a80-ba3c-11e9-9481-c8115b55a0de.png) --- 没错,会发现,假如我在点击按钮之后,再去修改UserName,这时候两者会表现出不同的行为。 FunC会记录点击按钮那一刻的值(通常这也是我们想要的),而ClassC则会取触发事件时的UserName。 导致这两者的区别是我们的ClassC在触发的时候,才去取当前的props.name,而FunC呢每一次渲染都会保存当前的状态 _(划重点这一点很重要,后面还会出现,很多人没有理解这一点经常写bug)_ 那么我们可以避免这种情况吗?或者说我们怎样实现,在触发`Console`的时候取的是按钮点击时的值? 这显然是可以的,我们可以在点击的时候,先捕获当前的Name,然后通过传参的方式来实现。 [live demo2](https://codesandbox.io/s/hook-demo1-gus3k?fontsize=14) ![hook1_demo2](https://user-images.githubusercontent.com/11730463/62720929-a6757e00-ba3d-11e9-826d-ea7d862a22c2.png) 这种实现方式在React里面很常见,但是他会有另一种隐患,假如我现在需要的不止有Name,还有email、phone等,或者我需要读取的不是props还包含了state,那是不是得一个一个捕获传参... ![hoo1_demo2_2](https://user-images.githubusercontent.com/11730463/62721457-cfe2d980-ba3e-11e9-9396-bf0c89cb4c0c.png) __当然 我们还有另一种简单粗暴而又不是很常见的做法,我们可以把所有的逻辑都挪到`render`方法里面__ [live...
__本文讲的主要部分是 从 `ReactDOM.render` 调用到 `fiber tree` 创建之间的准备步骤,主要包括了 `ReactRoot`的创建,优先级以及同异步渲染方式的确定还有 `FiberTreeRoot` 的准备。__ 对一些比较经典的东西可能会简单带过,因为目前主要是梳理整个 React 的运行机制,而关于某一些细点,后面可能会独立出来说会比较清晰。 ------ 在开始之前,我们要先知道一个事情就是:平时我们写React,都要引入多一个 __'react-dom'__,用 `ReactDOM.render`来把React生成的`ReactElement`渲染到 DOM Tree 中。 __也就是说我们引入的React负责ReactElement组件相关的东西,渲染层面抽出来交给,ReactDOM、 ReactNative,这种分离这也赋予了React跨终端渲染的能力。__ 我们先来写个小demo,后面顺着这个demo断点来看代码会容易很多,本文以第一次渲染的情况做为探讨的情况(这也意味着这个阶段不会进行diff的阶段,后面可能会把diff当一个点抽出来说)。 ![demo-code](https://user-images.githubusercontent.com/11730463/48393448-92b91780-e74a-11e8-8e44-7258ca3f4b0d.png) 首先我们看一下 `React.render(, document.getElementById('container'))`,这里面的``首先会被babel调用 `React.createElement`生成为ReactElement,具体可以看第二篇 [React源码系列(二): 从jsx到createElement](./2)...
其实从Fork仓库到现在,断断续续看了两个月的React源码。这里写下看源码的感受、心得。 首先说一下为什么拖了两个月才开始写总结: > 最近工作比较忙,没有比较整块的时间来看源码 要准备专升本的考试,所以重心转移到学习那块去 React是一个社区比较活跃的框架,意味着社区很多人都贡献了代码,代码风格比起vue可能比较杂 里面很多公用变量,加上函数调用栈无比的深,容易看着看着就找不到北 这次是整个过程看下来,目的主要是了解整一个框架的运作,而不是针对某个功能点,所以比较吃力 绝不是因为新来了前端妹纸,导致分心了 (可恶 ![3](https://user-images.githubusercontent.com/11730463/48298341-b1bf6b80-e4f6-11e8-8e4f-9bf65d7af9e0.jpg) # 阅读准备 __这里先附上[有调试信息以及部分可能有误的注释的react仓库](https://github.com/jsonz1993/react),基于react16.4.1的。__ ### fork 仓库 首先很重要的一点就是,最好最好,不要直接下载React仓库,而是先Fork到自己的仓库,再clone到本地 为什么呢? 因为我们在阅读代码的时候,避免不了自己写注释,改一些变量让他跑向我们需要的分支。你如果是直接下载的话,自己修改的代码既不能提交到远程,也无法和别人共享。我这次就是吃了这个亏,虽然说可以改远程仓库地址push到自己的Github,但是就觉得很奇怪,所以是重新fork之后把修改的文件copy过去..... ### 找到入口文件 这里可以参考之前看 [`create-react-app`](https://jsonz1993.github.io/2018/05/create-react-app-o/) 的方法,由目录结构与`package.json`去找。 React项目是多包共用一套构建工具,包都放在 `packages/*`, 可以看到有 `react`、`react-dom`、`events`等文件夹,基本上可以靠文件夹的名字猜到放的是什么模块的东西。 ###...
前面我们已经讲了React渲染过程 [JSX到ReactElement](./2) 再到 [ReactRoot的创建、fiberTreeRoot的创建以及确定任务优先级等](./3)。 __接下来就是看React怎么生成整一棵 fiberTree,以及怎么把fiberTree对应到浏览器的DomTree。__ # 第四阶段 递归创建 fiber tree ## beginWork ![begin-work](https://user-images.githubusercontent.com/11730463/48458585-ecc8e400-e801-11e8-8d8e-05936cbcf417.png) `beginWork` 应该是第一个具体操作到fiber的方法,会根据我们 `workInProgress.tag` 来调用对应的操作方法来创建一个fiber节点,绑定到fiber tree上面,然后返回下一个工作单元(`nextUnitOfWork`)回到 `workLoop` 继续循环这个过程,直到整个fiber tree都创建完毕。 我们举两个例子来看具体的fiber操作做了什么东西,如果workInProgress是 `HostRoot` ,即我们一直说的`fiberTreeRoot`,这时候会调用`updateHostRoot`处理,如果是`ReactClass`的类型,就会调用`updateClassComponent`处理。 ## updateHostRoot _HostRoot类型 FiberTreeROOT_ 比如我们现在...
我们先思考两个问题 - 浏览器是怎么识别我们写的jsx? - 为什么甚至在我们的代码并没有使用 React 的情况下,也需要在文件顶部写 `import React from 'react'` # jsx 首先,什么是jsx? jsx 一种 JavaScript 的语法扩展,你可以在里面写你的 html + js。 ![jsx](https://user-images.githubusercontent.com/11730463/48298932-a2ddb680-e500-11e8-87c6-be276405f933.png) 然后babel就会帮我们调用 `React.createElement`。 __这也是为什么我们就算文件内没用到 React,也需要引入的原因。__ 以下两种写法的结果是一样的,一个是手动调用,一个是babel帮忙做了这层操作。 ![jsx-createelement](https://user-images.githubusercontent.com/11730463/48298935-aa9d5b00-e500-11e8-820f-ec2bf089d46d.png) # createElement(type,...
大家如果用的时候发现说报 `Cannot read property 'update' of undefined` 是因为 `react.addons.update` 这个接口已经被独立出 `react`了。[https://github.com/facebook/react/issues/2909](https://github.com/facebook/react/issues/2909) 解决的办法可以自行Google `react.addons.update` 寻找替换的npm 然后在[代码里](https://github.com/shigebeyond/react-native-sk-countdown/blob/master/CountDownText.js#L22) 重置该变量即可。 如果大家想偷个懒, 可以到[jsonz.github](https://github.com/jsonz1993/wheel/tree/master/react-native-countdown)。 自己根据[shigebeyond](https://github.com/shigebeyond) 的代码造了一个小轮子。 改用es6语法 && 兼容新版本的 React && RN。 不过没有传到npm上 主要是懒~