Colin Aulds Colin Aulds - 29 days ago 9
React JSX Question

hello world reducer for react/redux

There are a few other hello world app questions with regard to react, but mine is specific to the reducer. Im not exactly sure what I should put in the reducer for my specific action.

Note*: I thought maybe i need to add a message: "" key value pair to my initial state and then declare a

var newState = Object.assign({}, state, {
message:"hello world"
});


into my if statement in the reducer, then dispatch it in the component, but that seems unneccesary since it should always print hello world, so hard coding seems more efficient. Hopefully there isn't too much clutter in this question as well.

Here is my component:

var HelloWorld = React.createClass({
helloWorld: function() {
this.props.dispatch(actions.printHello());
},
render: function() {
return (
<div className="HelloWorld">
<h1>Hello World!</h1>
</div>
);
}
});

var Container = connect()(HelloWorld);

module.exports = Container;


my action:

var $ = require("jquery")

var PRINT_HELLO = 'PRINT_HELLO';
var printHello = function() {
return {
type: GUESS_NUM
};
};

exports.PRINT_HELLO = PRINT_HELLO;
exports.printHello = printHello;


and reducer:

var actions = require('./actions');

var initialRepositoryState = {
type: null
};

var capstoneApp = function (state,action) {
state = state || initialRepositoryState;


if (action.type === actions.PRINT_HELLO) {
var newState = Object.assign({}, state, {
message:"hello world"
});
return newState;
}
};


I don't think you will need my index.js but I will provide if necessary.
Thanks in advance for input!

Answer

The reducer holds your state. So the way of thinking about it is "what are the parts of my program that can change?" And then from there, the next question is "What is the minimal amount of state needed to hold on to my program?"

From looking at your example, I get the impression that you are trying to build an application that sometimes displays "hello world" in the UI. Let me make a few more interactions to help describe all the pieces.

Initially, I'll help you create a program that has an empty label and a button. When you click on the button, it will display "hello world".

Okay, so to answer the first question: What can change? The app can either display "hello world" or nothing. We could store that in a couple of different ways. If the string is hard-coded, like you've alluded to above, then really you have a bool of show the message, or not.

And to the second question: one truthy value is pretty much the definition of a minimal state. So let's make a reducer:

var initialState = {
    showMessage: false,
};

var reducer = function(state, action) {
    var newState = Object.assign({}, state);
    if (action.type === 'BUTTON_PRESS') {
        newState.showMessage = !newState.showMessage;
    }
    return newState;
}

Okay, so now we've created a reducer that, when it gets the BUTTON_PRESS action, it flips the bit of its state.

Now, let's talk about how to hook that reducer up to redux. Right now, the reducer is a plain javascript function. We just need to pass that store into redux with the initial state. [createStore][1]

P.S. I normally write ES2015 code so there may be small typos in the commonJS import syntax

var redux = require('redux');
var store = redux.createStore(reducer, initialState);

The next part is to look at redux-react. Redux-react is glue that works both ways in react. It connects data from the redux store to react props, and it connects react callbacks (such as a click) to redux actions.

So conceptually, it looks like this. You have a react component that has a button. When you click the button, we want to generate a 'BUTTON_PRESS' action. After this, your react component no longer cares what happens to BUTTON_PRESS. Its job is done. BUTTON_PRESS could do one of infinite things. Now, assume that redux-react does its job and gets the action passed to the reducer. The reducer computes its new logic and returns a new state. This new state has the value of showMessage. Then, redux-react does the other half of connecting and makes showMessage a prop for the component. Just to be clear, there is no explicit reason why the same react component has to respond to the state changed by your action. They could be different components.

To put it into bullet points, here is how the codeflow should work:

  1. We create an initial store with showMessage = false
  2. When creating the React component, we use connect to bind the showMessage to a prop, and to handle onClick of the button in the component to generate a 'BUTTON_PRESS' action.
  3. Since showMessage is false, there is originally only a button present.
  4. The user presses the button. React calls into the onClick handler
  5. We use redux-react to dispatch a BUTTON_PRESS event
  6. When redux gets an action, it calls the reducer with the current state and the action. The reducer is responsible for generating a new state in response to this action
  7. The reducer sets showMessage to true
  8. redux-react listens to store changes and when it changes it modifies the prop for the react component
  9. The prop changes so react calls render()
    1. Inside your render method you see that this.props.showMessage is true, so you display the message.

And here is how such a react component could be implemented. There are enough differences between React components in ES5 vs ES2015 that I'm just going to give you the ES2015 version and apologize again.

class HelloWorld extends Component {
    render() {
        const message = this.props.showMessage ? "Hello world!" : "";
        return (
        <div id="label">{message}</div>
        <div id="button" onClick={this.props.handleOnClick}>Toggle the message </div>
        );
    }
}

HelloWorld.propTypes = {
    showMessage: PropTypes.bool.isRequired,
    handleOnClick: PropTypes.func.isRequired,
};

const mapStateToProps = state => ({
    showMessage: state.showMessage,

});

const mapDispatchToProps = dispatch => ({
    handleOnClick: dispatch({ type: 'BUTTON_PRESS', payload: '' })
});

export default connect(mapStateToProps, mapDispatchToProps)(HelloWorld);

You can keep reading the docs but I hope that helps explain what all the parts are. Let me know if anything isn't clear. [1]: http://redux.js.org/docs/api/createStore.html

Comments