Skip to content

Instantly share code, notes, and snippets.

@justin808
Last active January 2, 2017 02:09
Show Gist options
  • Save justin808/c73089d97680c09cc8e032c5317abb3c to your computer and use it in GitHub Desktop.
Save justin808/c73089d97680c09cc8e032c5317abb3c to your computer and use it in GitHub Desktop.
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx
import { HELLO_WORLD_NAME_UPDATE } from '../constants/helloWorldConstants';
export const updateName = (text) => ({
type: HELLO_WORLD_NAME_UPDATE,
text,
});
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/constants/helloWorldConstants.jsx
/* eslint-disable import/prefer-default-export */
export const HELLO_WORLD_NAME_UPDATE = 'HELLO_WORLD_NAME_UPDATE';
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/reducers/helloWorldReducer.jsx
import { combineReducers } from 'redux';
import { HELLO_WORLD_NAME_UPDATE } from '../constants/helloWorldConstants';
const name = (state = '', action) => {
console.log(action);
switch (action.type) {
case HELLO_WORLD_NAME_UPDATE:
return action.text;
default:
return state;
}
};
const helloWorldReducer = combineReducers({ name });
export default helloWorldReducer;
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/store/helloWorldStore.jsx
import { createStore } from 'redux';
import helloWorldReducer from '../reducers/helloWorldReducer';
const configureStore = (railsProps) => (
createStore(helloWorldReducer, railsProps)
);
export default configureStore;
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/startup/helloWorldApp.jsx
import React from 'react';
import ReactOnRails from 'react-on-rails';
import { Provider } from 'react-redux';
import configureStore from '../store/helloWorldStore';
import HelloWorldContainer from '../containers/HelloWorldContainer';
// See documentation for https://github.com/reactjs/react-redux.
// This is how you get props from the Rails view into the redux store.
// This code here binds your smart component to the redux store.
// railsContext provides contextual information especially useful for server rendering, such as
// knowing the locale. See the React on Rails documentation for more info on the railsContext
const HelloWorldApp = (props, _railsContext) => (
<Provider store={configureStore(props)}>
<HelloWorldContainer />
</Provider>
);
export default HelloWorldApp;
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/containers/HelloWorldContainer.jsx
// Simple example of a React "smart" component
import { connect } from 'react-redux';
import HelloWorld from '../components/HelloWorld';
import * as actions from '../actions/helloWorldActionCreators';
import { updateName } from '../actions/helloWorldActionCreators'
// Which part of the Redux global state does our component want to receive as props?
const mapStateToProps = (state) => ({ name: state.name });
const mapDispatchToProps = (dispatch) => {
return {
onNameUpdate: (name) => {
dispatch(updateName(name))
}
}
};
// Don't forget to actually use connect!
// Note that we don't export HelloWorld, but the redux "connected" version of it.
// See https://github.com/reactjs/react-redux/blob/master/docs/api.md#examples
export default connect(mapStateToProps, mapDispatchToProps)(HelloWorld);
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
// app/bundles/HelloWorld/components/HelloWorld.jsx
import React, { PropTypes } from 'react';
const HelloWorld = ({name, onNameUpdate}) => {
return (
<div>
<h3>
Hello, {name}!
</h3>
<hr />
<form >
<label htmlFor="name">
Say hello to:
</label>
<input
id="name"
type="text"
value={name}
onChange={(e) => onNameUpdate(e.target.value)}
/>
</form>
</div>
)
}
HelloWorld.propTypes = {
name: PropTypes.string.isRequired,
onNameUpdate: PropTypes.func.isRequired
}
export default HelloWorld;
@robwise
Copy link

robwise commented Jan 2, 2017

@justin

  1. No reason to, I tend to write my reducers this way now as well as it's much easier to manage a bunch of combined reducers rather than one monolith reducer
  2. They're not required; this file would work as it's written. However, the question is what your goal is. Do you want to do the simplest thing possible, or do you want to create a skeleton for how one might actually organize their files in the real world?

I don't personally feel the mapDispatchToProps function is necessary, as the shorthand/sugar was added to Redux a while ago that just lets you pass an object with the actions inside and it will automatically bind them to functions of the same name (this shorter way is how we had it previously).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment