From 07a1ec618de8e221a53dcc79759a8442c1eadb17 Mon Sep 17 00:00:00 2001 From: Artem Miroshnyk Date: Sun, 22 May 2016 16:38:27 +0200 Subject: [PATCH] Introduce redux store --- package.json | 6 +++- src/actions.js | 5 +++ src/app.js | 93 +++++++++++++++----------------------------------- src/form.js | 1 - src/index.js | 10 ++++-- src/reducer.js | 43 +++++++++++++++++++++++ src/store.js | 8 +++++ 7 files changed, 97 insertions(+), 69 deletions(-) create mode 100644 src/actions.js create mode 100644 src/reducer.js create mode 100644 src/store.js diff --git a/package.json b/package.json index 98a5d96..4c236b2 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,10 @@ "dependencies": { "domready": "^1.0.8", "react": "^15.1.0", - "react-dom": "^15.1.0" + "react-dom": "^15.1.0", + "react-redux": "^4.4.5", + "redux": "^3.5.1", + "object-assign": "4.0.1", + "redux-actions": "^0.9.1" } } diff --git a/src/actions.js b/src/actions.js new file mode 100644 index 0000000..67dd4d7 --- /dev/null +++ b/src/actions.js @@ -0,0 +1,5 @@ +import { createAction } from 'redux-actions'; + +export const activateApplication = createAction('ACTIVATE_APPLICATION'); +export const updateFormValue = createAction('UPDATE_FORM_VALUE', (propertyName, value) => ({propertyName, value})); + diff --git a/src/app.js b/src/app.js index 963b43c..b3e7515 100644 --- a/src/app.js +++ b/src/app.js @@ -1,91 +1,34 @@ import React from 'react'; -import {findDOMNode} from 'react-dom'; - import Form from './form.js'; +import { connect } from 'react-redux'; +import * as actions from './actions.js'; +import { bindActionCreators } from 'redux'; -const fields = [ - { - id: 'name', - inputComponentName: 'TextInput', - placeholder: 'Enter your name' - }, - { - id: 'age', - inputComponentName: 'TextInput', - placeholder: 'Enter your age' - }, - { - id: 'gender', - inputComponentName: 'Radio', - options: ['male', 'female', 'other'] - } -]; - -export default class App extends React.Component { +class App extends React.Component { constructor(props) { super(props); - this.state = { - isActive: false, - formData: { - name: '', - age: '' - } - }; - this.toggleActiveState = this.toggleActiveState.bind(this); this.handleFormFieldChange = this.handleFormFieldChange.bind(this); } render() { - const style = this.state.isActive + const style = this.props.appState.isActive ? {backgroundColor: 'teal', color: 'white'} : {}; return ( -
+

Marathon Estimate

-
); } - componentDidMount() { - const node = findDOMNode(this.refs['google-map']); - const el = document.createElement('p'); - el.innerHTML = 'hello!'; - node.appendChild(el); - el.addEventListener('click', this.onCustomElementClick); - this.el = el; - } - - componentWillUnmount() { - this.el.removeEventListener('click', this.onCustomElementClick); - } - - onCustomElementClick() { - alert('hello!'); - } - - toggleActiveState() { - this.setState({ - isActive: !this.state.isActive - }); - } - handleFormFieldChange(value, id) { - this.setState({ - formData: Object.assign({}, this.state.formData, { - [id]: value - }) - }); + this.props.actions.updateFormValue(id, value); } // TODO: implement @@ -96,3 +39,23 @@ export default class App extends React.Component { }); } } + +function mapStateToProps(state) { + return { + appState: state + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators(actions, dispatch), + }; +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(App); + + + diff --git a/src/form.js b/src/form.js index cad1be1..cdac4d8 100644 --- a/src/form.js +++ b/src/form.js @@ -12,7 +12,6 @@ export default function Form(props) { ); diff --git a/src/index.js b/src/index.js index 089559f..5874bef 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,16 @@ import React from 'react'; import {render} from 'react-dom'; import domReady from 'domready'; - import App from './app.js'; +import { Provider } from 'react-redux'; +import configureStore from './store.js'; + +const store = configureStore(); domReady(() => { const container = document.getElementById('app'); - render(, container); + render( + + + , container); }); diff --git a/src/reducer.js b/src/reducer.js new file mode 100644 index 0000000..4323aa6 --- /dev/null +++ b/src/reducer.js @@ -0,0 +1,43 @@ +import objectAssign from 'object-assign'; +import { handleActions } from 'redux-actions'; + +const initialState = { + fields: [ + { + id: 'name', + inputComponentName: 'TextInput', + placeholder: 'Enter your name', + value: '' + }, + { + id: 'age', + inputComponentName: 'TextInput', + placeholder: 'Enter your age', + value: '' + }, + { + id: 'gender', + inputComponentName: 'Radio', + options: ['male', 'female', 'other'], + value: [] + } + ], + isActive: false +}; + +const appState = handleActions({ + 'UPDATE_FORM_VALUE': function (state, action) { + let newState = objectAssign({}, state); + newState.fields = newState.fields.map(function(field) { + console.log(field); + if (field.id == action.payload.propertyName) { + field.value = action.payload.value; + } + return field; + }); + return newState; + }, + 'ACTIVATE_APPLICATION': (state, action) => objectAssign({}, state, {isActive: true}) +}, initialState); + +export default appState; diff --git a/src/store.js b/src/store.js new file mode 100644 index 0000000..4c12364 --- /dev/null +++ b/src/store.js @@ -0,0 +1,8 @@ +import { createStore, applyMiddleware, compose } from 'redux'; +import reducer from './reducer.js'; + +export default function configureStore(initialState) { + return createStore(reducer, initialState, + window.devToolsExtension ? window.devToolsExtension() : f => f + ); +}