Skip to content

Instantly share code, notes, and snippets.

@markbiek
Created January 26, 2017 16:40
Show Gist options
  • Select an option

  • Save markbiek/d0cd9695f38f23422237288471011517 to your computer and use it in GitHub Desktop.

Select an option

Save markbiek/d0cd9695f38f23422237288471011517 to your computer and use it in GitHub Desktop.
A minimal react/redux app (with some minor tweaks to work on CodePen)
//In action here: http://codepen.io/markbiek/pen/PWJJEX?editors=0010#0
/* Data functions */
/***************************************/
const { fromJS, mergeDeep } = Immutable;
/**
* getEarthquakes
* Calls a USGS API endpoint to get "significant" earthquakes in the last 30 days.
* On success, dispatches a 'GOT_DATA' message to the reducer.
*/
const getEarthquakes = () => {
axios.get('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_month.geojson')
.then((response) => {
store.dispatch({ type: 'GOT_DATA', data: response.data})
})
.catch(function (err) {
console.error(err);
});
};
/* Reducers */
/***************************************/
/**
* This is the format of our initial data structure. Once we get earthquake data, we'll set data to it.
* The state is an ImmutableJS object to make updating it easier.
*/
const testInitialState = fromJS({
data: {}
});
/**
* This reducer handles the 'GOT_DATA' message and updates our state.
*/
const testReducer = function (state = testInitialState, action) {
switch (action.type) {
case 'GOT_DATA':
//We use the Immutable.mergeDeep function to update the state with our data and return a new Immutable object
return state.mergeDeep({
data: action.data
});
default:
return state;
}
}
/* Store */
/***************************************/
const { combineReducers, createStore} = Redux;
const { Provider } = ReactRedux;
const { connect } = ReactRedux;
//If we add any other reducers, we need to add them here so they'll be part of the store
const reducers = combineReducers({
testState: testReducer
});
const store = createStore(reducers);
/* Index */
/***************************************/
/**
* App component
* Our main app component. It calls the function to load earthquake data when it's about to mount.
*/
class App extends React.Component {
componentWillMount() {
getEarthquakes();
}
render() {
return (
<div>
<h1>React/Redux Example</h1>
<p>This is a simple react/redux application which loads some data from an external resource.</p>
<TestComponent />
</div>
);
}
}
/* Components */
/***************************************/
/**
* TestComponent_
* This function receives all the earthquake data and displays the number of significant earthquakes.
*/
class TestComponent_ extends React.Component {
render() {
const { metadata } = this.props.data;
if (typeof metadata == 'undefined') {
//Data hasn't loaded yet
return (
<div>
Loading...
</div>
);
}
return (
<div>
<h2>Recent Earthquakes</h2>
<p>There have been <strong>{metadata.count}</strong> significant earthquakes in the last 30 days.</p>
</div>
);
}
}
//This is where we grab data from the store and map it to `this.props`
//We're currently grabbing _all_ the data but we could just as easily
//get parts of the data and assign them to whatever prop names we want.
const testComponentMapState = function(store) {
return {
data: store.testState.toJS().data
};
};
//Notice that the actual component class is call `TestComponent_` and we're creating a new const `TestComponent`.
//That way, we can use `<TestComponent />` in our App `render` method and the mapStateToProps stuff will work.
//This is CodePen specific. In a real website, `TestComponent` would live in a separate file
//and we'd `import` it into the `<App />` component file.
const TestComponent = connect(testComponentMapState)(TestComponent_);
/* Render */
/***************************************/
//Render the app to the DOM
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('app'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment