Skip to content

Commit

Permalink
Support hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
MQuy committed Jan 29, 2019
1 parent 14c508f commit 9b94390
Show file tree
Hide file tree
Showing 11 changed files with 465 additions and 186 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ The dead simple implementation of React for the learning purpose on how React wo
- [x] Global event handler
- [x] Fiber
- [x] Priority
- [ ] Hooks
- [x] Hooks
- [ ] Suspend
- [ ] Synthetic event
- [ ] Synthetic event
84 changes: 12 additions & 72 deletions demo/app.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,19 @@
import * as React from "../qreact";

class App extends React.Component {
constructor(props) {
super(props);

this.state = {
stories: [
{
id: 1,
name: "[Webpack] — Smart Loading Assets For Production",
url:
"https://hackernoon.com/webpack-smart-loading-assets-for-production-3571e0a29c2e",
},
{
id: 2,
name: "V8 Engine Overview",
url: "https://medium.com/@MQuy90/v8-engine-overview-7c965731ced4",
},
],
};
}

render() {
const { stories } = this.state;

return (
<div>
<ul>
{stories.map(story => (
<Story story={story} key={story.id} onRemove={this.removeStory} />
))}
</ul>
</div>
);
}

removeStory = story => () => {
const { stories } = this.state;

const index = stories.findIndex(s => s.id == story.id);
stories.splice(index, 1);

this.setState(stories);
};
}

class Story extends React.Component {
constructor(props) {
super(props);

this.state = { likes: Math.ceil(Math.random() * 100) };
}
render() {
const { story, onRemove } = this.props;
const { likes } = this.state;

return (
<li>
<button onClick={this.handleClick}>{likes}❤️</button>
<a href={story.url}>{story.name}</a>
<button onClick={onRemove(story)}>Remove</button>
</li>
);
}

handleClick = () => {
this.setState({
likes: this.state.likes + 1,
});
};
function Example() {
const [count, setCount] = React.useState(0);

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

React.render(
<React.unstable_AsyncMode>
<App />
</React.unstable_AsyncMode>,
<div>
<Example />
</div>,
document.getElementById("root"),
);
4 changes: 2 additions & 2 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"webpack-dev-server": "3.1.14"
},
"dependencies": {
"react": "16.3.0",
"react-dom": "16.3.3"
"react": "16.8.0-alpha.1",
"react-dom": "16.8.0-alpha.1"
}
}
103 changes: 24 additions & 79 deletions demo/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -949,11 +949,6 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=

asap@~2.0.3:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=

asn1.js@^4.0.0:
version "4.9.2"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a"
Expand Down Expand Up @@ -1459,11 +1454,6 @@ copy-descriptor@^0.1.0:
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=

core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=

core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
Expand Down Expand Up @@ -1804,13 +1794,6 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=

encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
dependencies:
iconv-lite "~0.4.13"

end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
Expand Down Expand Up @@ -2060,19 +2043,6 @@ faye-websocket@~0.11.1:
dependencies:
websocket-driver ">=0.5.1"

fbjs@^0.8.16:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"

figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
Expand Down Expand Up @@ -2520,7 +2490,7 @@ iconv-lite@0.4.23:
dependencies:
safer-buffer ">= 2.1.2 < 3"

iconv-lite@^0.4.4, iconv-lite@~0.4.13:
iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
Expand Down Expand Up @@ -2770,7 +2740,7 @@ is-regex@^1.0.4:
dependencies:
has "^1.0.1"

is-stream@^1.0.1, is-stream@^1.1.0:
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
Expand Down Expand Up @@ -2817,14 +2787,6 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=

isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"

js-levenshtein@^1.1.3:
version "1.1.6"
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
Expand Down Expand Up @@ -3254,14 +3216,6 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"

node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"

node-forge@0.7.5:
version "0.7.5"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df"
Expand Down Expand Up @@ -3681,14 +3635,7 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=

promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
dependencies:
asap "~2.0.3"

prop-types@^15.6.0:
prop-types@^15.6.2:
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==
Expand Down Expand Up @@ -3812,25 +3759,25 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"

react-dom@16.3.3:
version "16.3.3"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.3.tgz#af4c2aef9f6a66251a46da50253c860a67ae66d9"
integrity sha512-ALCp7ZbSGkqRDtQoZozKVNgwXMxbxf/IGOUMC2A0yF6JHeZrS8e2cOotPT87Vf4b7PKCuUVKU4/RDEXxToA/yA==
react-dom@16.8.0-alpha.1:
version "16.8.0-alpha.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.0-alpha.1.tgz#dab73b8354ba2e498e3127d18e29d4546cea889e"
integrity sha512-tZCUM8BpnwUHJmLnUWP9c3vVZxnCqYotj7s4tx7umojG6BKv745KIBtuPTzt0EI0q50GMLEpmT/CPQ8iA61TwQ==
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
scheduler "^0.13.0-alpha.1"

react@16.3.0:
version "16.3.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.3.0.tgz#fc5a01c68f91e9b38e92cf83f7b795ebdca8ddff"
integrity sha512-Qh35tNbwY8SLFELkN3PCLO16EARV+lgcmNkQnoZXfzAF1ASRpeucZYUwBlBzsRAzTb7KyfBaLQ4/K/DLC6MYeA==
react@16.8.0-alpha.1:
version "16.8.0-alpha.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.8.0-alpha.1.tgz#c2b32689f3b466d3ce85a634dd9035f789d2cd97"
integrity sha512-vLwwnhM2dXrCsiQmcSxF2UdZVV5xsiXjK5Yetmy8dVqngJhQ3aw3YJhZN/YmyonxwdimH40wVqFQfsl4gSu2RA==
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.0"
prop-types "^15.6.2"
scheduler "^0.13.0-alpha.1"

"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@~2.3.6:
version "2.3.6"
Expand Down Expand Up @@ -4070,6 +4017,14 @@ sax@^1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==

scheduler@^0.13.0-alpha.1:
version "0.13.0-alpha.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.0-alpha.1.tgz#753977fb4fb35d8cdd559868a11e46b640955556"
integrity sha512-W0sH0848sVuPKg+I18vTYQyzVtA4X1lrVgSeXK6KnOPUltFdJcY5nkbTkjGUeS/E0x+eBsNYfSdhJtGjT95njw==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"

schema-utils@^0.4.4:
version "0.4.7"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
Expand Down Expand Up @@ -4183,7 +4138,7 @@ set-value@^2.0.0:
is-plain-object "^2.0.3"
split-string "^3.0.1"

setimmediate@^1.0.4, setimmediate@^1.0.5:
setimmediate@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
Expand Down Expand Up @@ -4583,11 +4538,6 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

ua-parser-js@^0.7.18:
version "0.7.19"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b"
integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==

uglify-js@3.4.x:
version "3.4.9"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
Expand Down Expand Up @@ -4887,11 +4837,6 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==

whatwg-fetch@>=0.10.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==

which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
Expand Down
2 changes: 2 additions & 0 deletions qreact.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { render } from "./src/render";
import { createElement, REACT_ASYNC_MODE_TYPE } from "./src/createElement";
import { Component } from "./src/Component";
import { deferredUpdates } from "./src/FiberScheduler";
import { useState } from "./src/FiberHooks";

const unstable_AsyncMode = REACT_ASYNC_MODE_TYPE;

export {
render,
createElement,
Component,
useState,
deferredUpdates,
unstable_AsyncMode,
};
2 changes: 2 additions & 0 deletions src/Component.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class Component {
insertUpdateIntoFiber(fiber, update);
scheduleWork(fiber, expirationTime);
}

isReactComponent = {};
}

export const ReactInstanceMap = {
Expand Down
28 changes: 10 additions & 18 deletions src/Fiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
HostText,
ClassComponent,
Mode,
FunctionalComponent,
} from "./TypeOfWork";
import { REACT_ASYNC_MODE_TYPE, REACT_STRICT_MODE_TYPE } from "./createElement";
import { AsyncMode, StrictMode } from "./TypeOfMode";
Expand Down Expand Up @@ -95,7 +96,11 @@ export function createFiberFromElement(element, mode, expirationTime) {

let fiberTag;
if (typeof type === "function") {
fiberTag = ClassComponent;
if (shouldConstruct(type)) {
fiberTag = ClassComponent;
} else {
fiberTag = FunctionalComponent;
}
} else if (typeof type === "string") {
fiberTag = HostComponent;
} else {
Expand All @@ -109,7 +114,7 @@ export function createFiberFromElement(element, mode, expirationTime) {
mode |= StrictMode;
break;
default: {
if (typeof type === "object" && type !== null) {
if (typeof type === "object" && type != null) {
if (typeof type.tag === "number") {
// Currently assumed to be a continuation and therefore is a
// fiber already.
Expand Down Expand Up @@ -144,20 +149,7 @@ export function createFiberFromText(content, mode, expirationTime) {
return fiber;
}

function createFiberFromElementType(type, key) {
let fiber;
if (typeof type === "function") {
fiber = new FiberNode(ClassComponent, key);
fiber.type = type;
} else if (typeof type === "string") {
fiber = new FiberNode(HostComponent, key);
fiber.type = type;
} else if (
typeof type === "object" &&
type != null &&
typeof type.tag === "number"
) {
fiber = type;
}
return fiber;
function shouldConstruct(Component) {
const prototype = Component.prototype;
return !!(prototype && prototype.isReactComponent);
}

0 comments on commit 9b94390

Please sign in to comment.