Created
January 26, 2017 16:40
-
-
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)
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
| //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