Build Your Own Flux

Architecture in the Client

What’s the idea behind our own Flux?

{
type: ‘ADD_ITEM_TO_TOP’,
item: {
name: 'John Doe',
id: 1234
}
}

Enter with a Service Handler

{
type: 'STARTPAGE:ENTER',
user: 12345
}
dispatcher.registerService(
'STARTPAGE:ENTER',
function(action, dispatch) {
http.get('/user/' + action.user + '/stories').then(stories => {
dispatch({
type: 'STARTPAGE:INCOMING',
stories: stories
});
}).catch(err => {
dispatch({
type: 'STARTPAGE:SERVER_ERROR',
error: err
});
});
)}
);

Modify the State

dispatcher.registerReducer(
'STARTPAGE:ENTER',
function(stateTools, action) {
return stateTools.transform('startpage', {
message: 'Your latest stories are being fetched'
});
)}
);
dispatcher.registerReducer(
'STARTPAGE:INCOMING',
function(previousState, action, transform) {
return transform(previousState, {
startpageMessage: '',
startpageStories: action.stories
});
}
)

Create a State Aware Component

class StoryList extends React.Component { …}
class StoryList extends StoreComponent { … }
constructor() {
super();
registerFor({
startpageMessage: 'No information available',
startpageStories: []
};
)}
render() {
return(
<main>
<div class="message">
{this.state.startpageMessage}
</div>
<ul class="stories">
{this.state.startpageStories.map(story => (
<StartpageStory story={story}/> // #A
))}
<ul>
</main>
)
}

Implementing the StoreComponent

class StoreComponent extends React.Component { // #A
constructor() {
super();
this.store = dispatcher.getStore(); // #B
}

componentDidMount() {
this.listenerId =
this.store.onChange(
this._handleChange.bind(this)
); // #C
}

componentWillUnmount() {
this.store.removeListener(this.listenerId); // #D
}

registerFor(items) {
this.registeredKeys = items;
this._setStateFromStore(); // #E
}

_setStateFromStore() {
const newState = {};
for(let key of Object.keys(this.registeredKeys)) {
newState[key] = this.store.get(key) !== undefined ?
this.store.get(key) :
this.registeredKeys[key];
}
}
this.setState(newState); // #F
}

_handleChange(state, keys) {
if(this._intersection(keys, this.keys).length > 0) {
this._setStateFromStore(); // #C
}
}

_intersection(keys1, keys2) {
return keys1.filter(key => keys2.indexOf(key) > -1)
}
}

Summary

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store