Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor to React Fiber #28

Merged
merged 8 commits into from
Jul 27, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions package/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
const snapShot = [];
const snapShot = { tree: null };

const mode = { jumping: false };

const linkState = require('./linkState')(snapShot, mode);
const linkFiber = require('./linkFiber')(snapShot, mode);
const timeJump = require('./timeJump')(snapShot, mode);
const unlinkState = require('./unlinkState')(snapShot);

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

window.addEventListener('message', ({ data: { action, payload } }) => {
console.log(action, payload);
if (action === 'jumpToSnap') {
timeJump(payload);
} else if (action === 'stepToSnap') {
payload.forEach(snap => timeJump(snap));
switch (action) {
case 'jumpToSnap':
timeJump(payload);
break;
case 'stepToSnap': {
const { steps, speed } = payload;
console.log('i would like to step through here');
break;
}
default:
}
});

module.exports = {
linkState,
unlinkState,
timeJump,
getShot,
linkFiber,
getTree,
};
72 changes: 72 additions & 0 deletions package/linkFiber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// links component state tree to library
// changes the setState method to also update our snapshot
const Tree = require('./tree');

module.exports = (snap, mode) => {
let fiberRoot = null;
let first = true;

function sendSnapshot() {
// don't send messages while jumping
if (mode.jumping) return;
const payload = snap.tree.getCopy();
window.postMessage({
action: 'recordSnap',
payload,
});
}

function changeSetState(component) {
// check that setState hasn't been changed yet
if (component.setState.name === 'newSetState') return;

// make a copy of setState
const oldSetState = component.setState.bind(component);

function newSetState(state, callback = () => { }) {
// continue normal setState functionality, except add sending message middleware
if (first) {
updateSnapShotTree();
sendSnapshot();
first = false;
}
oldSetState(state, () => {
updateSnapShotTree();
sendSnapshot();
callback();
});
}

// replace component's setState so developer doesn't change syntax
component.setState = newSetState;
}

function createTree(currentFiber, tree = new Tree('root')) {
if (!currentFiber) return tree;

const { sibling, stateNode, child } = currentFiber;

let nextTree = tree;
if (stateNode && stateNode.state) {
nextTree = tree.appendChild(stateNode);
changeSetState(stateNode);
}

// iterate through siblings
createTree(sibling, tree);
// iterate through children
createTree(child, nextTree);

return tree;
}

function updateSnapShotTree() {
const { current } = fiberRoot;
snap.tree = createTree(current);
}
return (container) => {
const { _reactRootContainer: { _internalRoot } } = container;
fiberRoot = _internalRoot;
updateSnapShotTree();
};
};
65 changes: 0 additions & 65 deletions package/linkState.js

This file was deleted.

5 changes: 0 additions & 5 deletions package/package-lock.json

This file was deleted.

32 changes: 27 additions & 5 deletions package/timeJump.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
module.exports = (snapShot, mode) => {
return (newSnapShot) => {
mode.jumping = true;
newSnapShot.forEach(async (state, i) => {
await snapShot[i].setStateAsync(state);
// traverses given tree by accessing children through coords array
function traverseTree(tree, coords) {
let curr = tree;
coords.forEach((coord) => {
curr = curr.children[coord];
});
return curr;
}

module.exports = (origin, mode) => {
// recursively change state of tree
function jump(target, coords = []) {
const originNode = traverseTree(origin.tree, coords);

// set the state of the origin tree
originNode.component.setState(target.component.state, () => {
// iterate through new children once state has been set
target.children.forEach((child, i) => {
jump(child, coords.concat(i));
});
});
}


return (target) => {
// setting mode disables setState from posting messages to window
mode.jumping = true;
jump(target);
mode.jumping = false;
};
};
43 changes: 43 additions & 0 deletions package/tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class Tree {
constructor(component) {
// special case when component is root
// give it a special state = 'root'
// a setState function that just calls the callback instantly
this.component = (component === 'root') ? { state: 'root', setState: (partial, callback) => callback() } : component;
this.children = [];
}

appendChild(component) {
const child = new Tree(component);
this.children.push(child);
return child;
}

// deep copies only the state of each component and creates a new tree
getCopy(copy = new Tree(null)) {
const { state } = this.component;
if (!copy.component) copy.component = { state };

// copy state of children
copy.children = this.children.map(child => new Tree({ state: child.component.state }));

// copy children's children recursively
this.children.forEach((child, i) => child.getCopy(copy.children[i]));
return copy;
}

// print out the tree in the console
print() {
const children = ['children: '];
this.children.forEach((child) => {
children.push(child.component.state);
});
if (children.length === 1) console.log(this.component.state);
else console.log(this.component.state, ...children);
this.children.forEach((child) => {
child.print();
});
}
}

module.exports = Tree;
12 changes: 0 additions & 12 deletions package/unlinkState.js

This file was deleted.