javascript - How to Redux a Reactjs crime map application -
i working on demo react application - , important add redux this. please review following code , me invoke redux appropriately.
i understand how add sister components later on such application share communication channel - if create master/slave relationship between charts/components such.
// index.js
import react, { component } 'react' import { render } 'react-dom' //import { provider } 'react-redux' //import { createstore } 'redux' import mapchart './modules/mapchart/mapchart' import './index.css' // how you'll icon links // instead of switch loads of repetitive bytes const iconmap = { 'anti-social-behaviour': 'green-dot', 'burglary': 'red-dot', 'criminal-damage-arson': 'yellow-dot', 'drugs': 'purple-dot', 'other-theft': 'pink-dot', 'shoplifting': 'blue-dot', 'vehicle-crime': 'orange-dot', 'other-crime': 'ltblue-dot' } // class because needs state class crimemap extends component { // have make sure have // transform-class-properties feature in babel // otherwise set initial state in constructor // constructor(props) { // super(props) // this.state = { markers: [] } // } state = { markers: [] } componentdidmount() { // use fetch instead of jquery // jquery big lib loading fetching fetch(this.props.source) .then( response => response.json() ) .then( json => this.setstate({ markers: this.maplayerdata(json) }), err => { // handle errors } ) } // store data want pass props each marker // instead of mapping directly in mapchart every time renders maplayerdata(markers) { // use standard map function instead of $.each // destructuring saves time , repetition return markers.map(({ category, location }) => ({ // use template string , simple map of icon names icon uri icon: 'http://maps.google.com/mapfiles/ms/icons/'+ iconmap[category] +'.png', label: category, name: category, position: { lat: location.latitude, lng: location.longitude } })) } render() { // there's 1 layer, render directly return ( <div classname="app"> <mapchart markers={this.state.markers} /> </div> ) } } //https://data.police.uk/docs/method/crime-street/ render( <crimemap source="https://data.police.uk/api/crimes-street/all-crime?poly=52.268,0.543:52.794,0.238:52.130,0.478&date=2017-01" />, document.getelementbyid('root') );
// mapchart.js
import react 'react' // load you're using import { map, marker, googleapiwrapper } 'google-maps-react' import './mapchart.css' // stateless component, doesn't need state or event handlers const mapcontainer = ({ google, markers }) => ( <map google={google} initialcenter={{ lat: 52.268, lng: 0.543 }} zoom={9} > { markers.map((marker, i) => // since you've mapped data props need // can spread component <marker key={i} icon={marker.icon} title={marker.label} name={marker.name} position={{lat: marker.position.lat, lng: marker.position.lng}} /> ) } </map> ) export default googleapiwrapper({ apikey: 'xxxxx' })(mapcontainer)
// mapchart.css
/* set map height explicitly define size of div * element contains map. */ #map { height: 100%; } /* optional: makes sample page fill window. */ html, body { height: 100%; margin: 0; padding: 0; }
/////////////
this far have got adding redux -- getting error
actions must plain objects. use custom middleware async actions. basing of example - don't understand how add/define thunk? is?
http://jsfiddle.net/cdagli/b2uq8704/6/
index.js
import react, { component } 'react' import { render } 'react-dom' import {provider, connect} 'react-redux' import {createstore, applymiddleware} 'redux' import thunk 'redux-thunk'; import mapchart './modules/mapchart/mapchart' import './index.css' function fetchpostsrequest(){ return { type: "fetch_request" } } function fetchpostssuccess(payload) { return { type: "fetch_success", payload } } function fetchpostserror() { return { type: "fetch_error" } } const reducer = (state = {}, action) => { switch (action.type) { case "fetch_request": return state; case "fetch_success": return {...state, posts: action.payload}; default: return state; } } function fetchpostswithredux() { return (dispatch) => { dispatch(fetchpostsrequest()); return fetchposts().then(([response, json]) =>{ if(response.status === 200){ dispatch(fetchpostssuccess(json)) } else{ dispatch(fetchpostserror()) } }) } } function fetchposts() { const url = 'https://data.police.uk/api/crimes-street/all-crime?poly=52.268,0.543:52.794,0.238:52.130,0.478&date=2017-01'; return fetch(url, { method: 'get'}) .then( response => promise.all([response, response.json()])); } // how you'll icon links // instead of switch loads of repetitive bytes const iconmap = { 'anti-social-behaviour': 'green-dot', 'burglary': 'red-dot', 'criminal-damage-arson': 'yellow-dot', 'drugs': 'purple-dot', 'other-theft': 'pink-dot', 'shoplifting': 'blue-dot', 'vehicle-crime': 'orange-dot', 'other-crime': 'ltblue-dot' } // class because needs state class crimemap extends component { // have make sure have // transform-class-properties feature in babel // otherwise set initial state in constructor // constructor(props) { // super(props) // this.state = { markers: [] } // } state = { markers: [] } componentdidmount() { console.log('prop ', this.props) // use fetch instead of jquery // jquery big lib loading fetching fetch(this.props.source) .then( response => response.json() ) .then( json => this.setstate({ markers: this.maplayerdata(json) }), err => { // handle errors } ) } // store data want pass props each marker // instead of mapping directly in mapchart every time renders maplayerdata(markers) { // use standard map function instead of $.each // destructuring saves time , repetition return markers.map(({ category, location }) => ({ // use template string , simple map of icon names icon uri icon: 'http://maps.google.com/mapfiles/ms/icons/'+ iconmap[category] +'.png', label: category, name: category, position: { lat: location.latitude, lng: location.longitude } })) } render() { // there's 1 layer, render directly return ( <div classname="app"> <mapchart markers={this.state.markers} /> </div> ) } } function mapstatetoprops(state){ return { posts: state.posts } } let container = connect(mapstatetoprops, {fetchpostswithredux})(crimemap); const store = createstore( reducer, applymiddleware(thunk) ); //https://data.police.uk/docs/method/crime-street/ render( <provider store={store}> <container/> </provider>, document.getelementbyid('root') );
here flow of code have shared 1. when component mounts, calls function 2. function "fetchpostswithredux" dispatches actions also, send api call server fetch data 3. when data received component re-renders updated data prop.
now if want use maplayerdata function give data component, without using "old fetch method", can mentioned below
add function naming componentwillreceiveprops
componentwillreceiveprops(nextprops){ this.setstate({markers: this.maplayerdata(nextprops.posts)}); }
once call this, state of component have data, have received api call
hope above solution has given clarity it.
Comments
Post a Comment