Created
February 26, 2018 01:03
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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