Skip to content

Instantly share code, notes, and snippets.

@treyhuffine
Created February 26, 2018 01:03
Show Gist options
  • Save treyhuffine/bba40fa81c7b2dc3aa5b49a64868f531 to your computer and use it in GitHub Desktop.
Save treyhuffine/bba40fa81c7b2dc3aa5b49a64868f531 to your computer and use it in GitHub Desktop.
A simple application to show an implementation of time travel debugging in Redux
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div>My background color is <span id="background"></span></div>
<div id="debugger">
<div>
<button id="previous">
previous
</button>
<button id="next">
next
</button>
</div>
<div id="timeline"></div>
</div>
<style>
html, body {
width: 100vw;
height: 100vh;
}
#debugger {
margin-top: 30px;
}
</style>
<script>
const textNode = document.getElementById('background');
const timelineNode = document.getElementById('timeline');
const createStore = (reducer, initialState) => {
const store = {};
store.state = initialState;
store.listeners = [];
store.getState = () => store.state;
store.subscribe = listener => {
store.listeners.push(listener);
};
store.dispatch = action => {
console.log('> Action', action);
store.state = reducer(store.state, action);
store.listeners.forEach(listener => listener());
};
return store;
};
const getInitialState = () => {
return {
r: 255,
g: 255,
b: 255,
};
};
const reducer = (state = getInitialState(), action) => {
switch (action.type) {
case 'SET_RGB':
return {
r: action.payload.r,
g: action.payload.g,
b: action.payload.b,
};
default:
return state;
}
};
const store = createStore(reducer);
const setBackgroundColor = () => {
const state = store.getState();
const { r, g, b } = state;
const rgb = `rgb(${r}, ${g}, ${b})`;
document.body.style.backgroundColor = rgb;
textNode.innerHTML = rgb;
};
store.subscribe(setBackgroundColor);
const generateRandomColor = () => {
return Math.floor(Math.random() * 255);
};
// A simple event to dispatch changes
document.addEventListener('click', () => {
console.log('----- Previous state', store.getState());
store.dispatch({
type: 'SET_RGB',
payload: {
r: generateRandomColor(),
g: generateRandomColor(),
b: generateRandomColor(),
},
});
console.log('+++++ New state', store.getState());
});
const timeline = [];
let activeItem = 0;
const saveTimeline = () => {
timeline.push(store.getState());
timelineNode.innerHTML = timeline
.map(item => JSON.stringify(item))
.join('<br/>');
activeItem = timeline.length - 1;
};
store.subscribe(saveTimeline);
// FOR DEBUGGING PURPOSES ONLY
store.setState = desiredState => {
store.state = desiredState;
// Assume the debugger is injected last. We don't want to update
// the saved states as we're debugging.
const applicationListeners = store.listeners.slice(0, -1);
applicationListeners.forEach(listener => listener());
};
const previous = document.getElementById('previous');
const next = document.getElementById('next');
previous.addEventListener('click', e => {
e.preventDefault();
e.stopPropagation();
let index = activeItem - 1;
index = index <= 0 ? 0 : index;
activeItem = index;
const desiredState = timeline[index];
store.setState(desiredState);
});
next.addEventListener('click', e => {
e.preventDefault();
e.stopPropagation();
let index = activeItem + 1;
index = index >= timeline.length - 1 ? timeline.length - 1 : index;
activeItem = index;
const desiredState = timeline[index];
store.setState(desiredState);
});
store.dispatch({}); // Sets the inital state
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment