How to Recreate FCC React/Redux Challenge in CodePen?

Hi Campers!

I’ve done all the Redux and React-Redux challenges twice, and now I want to make sure I know how to use it in CodePen…

I have these CodePen settings

JavaScript Preprocessor: Babel

External Scripts/Libraries:

  • React
  • ReactDOM
  • Redux
I copied this entire code, which passed the final FCC React-Redux challenge (spoiler alert), into CodePen
// Redux:
const ADD = 'ADD';

const addMessage = (message) => {
  return {
    type: ADD,
    message: message
  }
};

const messageReducer = (state = [], action) => {
  switch (action.type) {
    case ADD:
      return [
        ...state,
        action.message
      ];
    default:
      return state;
  }
};

const store = Redux.createStore(messageReducer);

// React:
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;

// Change code below this line
class Presentational extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      input: ''
    }
    this.handleChange = this.handleChange.bind(this);
    this.submitMessage = this.submitMessage.bind(this);
  }
  handleChange(event) {
    this.setState({
      input: event.target.value
    });
  }
  submitMessage() {
    this.props.submitNewMessage(this.state.input);
    this.setState({
      input: ''
    });
  }
  render() {
    return (
      <div>
        <h2>Type in a new Message:</h2>
        <input
          value={this.state.input}
          onChange={this.handleChange}/><br/>
        <button onClick={this.submitMessage}>Submit</button>
        <ul>
          {this.props.messages.map( (message, idx) => {
              return (
                 <li key={idx}>{message}</li>
              )
            })
          }
        </ul>
      </div>
    );
  }
};
// Change code above this line

const mapStateToProps = (state) => {
  return {messages: state}
};

const mapDispatchToProps = (dispatch) => {
  return {
    submitNewMessage: (message) => {
      dispatch(addMessage(message))
    }
  }
};

const Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);

class AppWrapper extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Container/>
      </Provider>
    );
  }
};

Then I added:

ReactDOM.render(<Provider/>, document.getElementById('challenge-node'));

at the bottom of the JS, and

<div id="challenge-node"></div>

in the HTML.

But nothing shows up in the preview screen on my pen. What am I missing? :thinking: :smiley:

Thanks!
jan

Please learn to use your browser console. It was screaming the problem at you. ctrl-shft-j or something like it opens the browser console - the most useful tool a web dev has.

When I run your code, I get:

Uncaught ReferenceError: ReactRedux is not defined
at pen.js:40

(Ignore the warnings about fonts, that’s a problem with codepen.) This is telling you that ReactRedux is not defined, you haven’t imported it. Go to you Settings/JavaScript/Add External Scripts/Pens and use the “+ add another resource” to add a fourth library, https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.min.js.

This takes care of that problem. Ordinarily you would have to do some kind of an import to set up that variable, but Code Pen does it for you.

Now you have new errors in the browser along the lines of:

Uncaught Error: React.Children.only expected to receive a single React element child.
at invariant (VM64 react.development.js:203)
at Object.onlyChild [as only] (VM64 react.development.js:1229)
at o.render (react-redux.min.js:1)
at finishClassComponent (VM65 react-dom.development.js:13663)
at updateClassComponent (VM65 react-dom.development.js:13625)
at beginWork (VM65 react-dom.development.js:14293)
at performUnitOfWork (VM65 react-dom.development.js:16319)
at workLoop (VM65 react-dom.development.js:16358)
at HTMLUnknownElement.callCallback (VM65 react-dom.development.js:140)
at Object.invokeGuardedCallbackDev (VM65 react-dom.development.js:178)

This is a more inscrutable one but I track it down to the last line here, at the end:

//...
class AppWrapper extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Container/>
      </Provider>
    );
  }
};
ReactDOM.render(<Provider/>, document.getElementById('challenge-node'));

On that last line, you are trying to inject Provider into the DOM, but AppWrapper is what you want.

Once I do those two things, it’s working.