Skip to content

Commit 511a32f

Browse files
authored
Merge pull request #28 from oslabs-beta/rydang/treetime
refactor to React Fiber
2 parents fae06b2 + 390168c commit 511a32f

File tree

7 files changed

+158
-99
lines changed

7 files changed

+158
-99
lines changed

package/index.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
1-
const snapShot = [];
1+
const snapShot = { tree: null };
2+
23
const mode = { jumping: false };
34

4-
const linkState = require('./linkState')(snapShot, mode);
5+
const linkFiber = require('./linkFiber')(snapShot, mode);
56
const timeJump = require('./timeJump')(snapShot, mode);
6-
const unlinkState = require('./unlinkState')(snapShot);
77

8-
const getShot = () => snapShot.map(({ component }) => component.state);
8+
const getTree = () => snapShot.tree.getCopy();
99

1010
window.addEventListener('message', ({ data: { action, payload } }) => {
11-
console.log(action, payload);
12-
if (action === 'jumpToSnap') {
13-
timeJump(payload);
14-
} else if (action === 'stepToSnap') {
15-
payload.forEach(snap => timeJump(snap));
11+
switch (action) {
12+
case 'jumpToSnap':
13+
timeJump(payload);
14+
break;
15+
case 'stepToSnap': {
16+
const { steps, speed } = payload;
17+
console.log('i would like to step through here');
18+
break;
19+
}
20+
default:
1621
}
1722
});
1823

1924
module.exports = {
20-
linkState,
21-
unlinkState,
2225
timeJump,
23-
getShot,
26+
linkFiber,
27+
getTree,
2428
};

package/linkFiber.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// links component state tree to library
2+
// changes the setState method to also update our snapshot
3+
const Tree = require('./tree');
4+
5+
module.exports = (snap, mode) => {
6+
let fiberRoot = null;
7+
let first = true;
8+
9+
function sendSnapshot() {
10+
// don't send messages while jumping
11+
if (mode.jumping) return;
12+
const payload = snap.tree.getCopy();
13+
window.postMessage({
14+
action: 'recordSnap',
15+
payload,
16+
});
17+
}
18+
19+
function changeSetState(component) {
20+
// check that setState hasn't been changed yet
21+
if (component.setState.name === 'newSetState') return;
22+
23+
// make a copy of setState
24+
const oldSetState = component.setState.bind(component);
25+
26+
function newSetState(state, callback = () => { }) {
27+
// continue normal setState functionality, except add sending message middleware
28+
if (first) {
29+
updateSnapShotTree();
30+
sendSnapshot();
31+
first = false;
32+
}
33+
oldSetState(state, () => {
34+
updateSnapShotTree();
35+
sendSnapshot();
36+
callback();
37+
});
38+
}
39+
40+
// replace component's setState so developer doesn't change syntax
41+
component.setState = newSetState;
42+
}
43+
44+
function createTree(currentFiber, tree = new Tree('root')) {
45+
if (!currentFiber) return tree;
46+
47+
const { sibling, stateNode, child } = currentFiber;
48+
49+
let nextTree = tree;
50+
if (stateNode && stateNode.state) {
51+
nextTree = tree.appendChild(stateNode);
52+
changeSetState(stateNode);
53+
}
54+
55+
// iterate through siblings
56+
createTree(sibling, tree);
57+
// iterate through children
58+
createTree(child, nextTree);
59+
60+
return tree;
61+
}
62+
63+
function updateSnapShotTree() {
64+
const { current } = fiberRoot;
65+
snap.tree = createTree(current);
66+
}
67+
return (container) => {
68+
const { _reactRootContainer: { _internalRoot } } = container;
69+
fiberRoot = _internalRoot;
70+
updateSnapShotTree();
71+
};
72+
};

package/linkState.js

Lines changed: 0 additions & 65 deletions
This file was deleted.

package/package-lock.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

package/timeJump.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
1-
module.exports = (snapShot, mode) => {
2-
return (newSnapShot) => {
3-
mode.jumping = true;
4-
newSnapShot.forEach(async (state, i) => {
5-
await snapShot[i].setStateAsync(state);
1+
// traverses given tree by accessing children through coords array
2+
function traverseTree(tree, coords) {
3+
let curr = tree;
4+
coords.forEach((coord) => {
5+
curr = curr.children[coord];
6+
});
7+
return curr;
8+
}
9+
10+
module.exports = (origin, mode) => {
11+
// recursively change state of tree
12+
function jump(target, coords = []) {
13+
const originNode = traverseTree(origin.tree, coords);
14+
15+
// set the state of the origin tree
16+
originNode.component.setState(target.component.state, () => {
17+
// iterate through new children once state has been set
18+
target.children.forEach((child, i) => {
19+
jump(child, coords.concat(i));
20+
});
621
});
22+
}
23+
24+
25+
return (target) => {
26+
// setting mode disables setState from posting messages to window
27+
mode.jumping = true;
28+
jump(target);
729
mode.jumping = false;
830
};
931
};

package/tree.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
class Tree {
2+
constructor(component) {
3+
// special case when component is root
4+
// give it a special state = 'root'
5+
// a setState function that just calls the callback instantly
6+
this.component = (component === 'root') ? { state: 'root', setState: (partial, callback) => callback() } : component;
7+
this.children = [];
8+
}
9+
10+
appendChild(component) {
11+
const child = new Tree(component);
12+
this.children.push(child);
13+
return child;
14+
}
15+
16+
// deep copies only the state of each component and creates a new tree
17+
getCopy(copy = new Tree(null)) {
18+
const { state } = this.component;
19+
if (!copy.component) copy.component = { state };
20+
21+
// copy state of children
22+
copy.children = this.children.map(child => new Tree({ state: child.component.state }));
23+
24+
// copy children's children recursively
25+
this.children.forEach((child, i) => child.getCopy(copy.children[i]));
26+
return copy;
27+
}
28+
29+
// print out the tree in the console
30+
print() {
31+
const children = ['children: '];
32+
this.children.forEach((child) => {
33+
children.push(child.component.state);
34+
});
35+
if (children.length === 1) console.log(this.component.state);
36+
else console.log(this.component.state, ...children);
37+
this.children.forEach((child) => {
38+
child.print();
39+
});
40+
}
41+
}
42+
43+
module.exports = Tree;

package/unlinkState.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)