2

I am writing an app using Redux and can't get a Redux connect()ed component to render at all.

import { createStore } from 'redux';
import { Provider, connect } from 'react-redux';

var store = createStore((s, a) => s, {hello: "WORLD"});

class App extends React.Component {
  render() { return <h1> Hello, world! </h1>; }
}
var connectedApp = connect(function(s) { debugger })(App);

$(document).ready(function() {
  var target = document.getElementById("root");

  // DOES render
  React.render(<App/>, target);

  // Never renders
  React.render(<connectedApp/>, target);
});

The app is using babel, babelify, redux and redux-react.

Returning an object inside of connect() did not seem to modify this.props in the component, either. The debugger statement passed to connect never fires.

Is there something wrong with this code? Why isn't the component rendering? Why does the debugger statement never fire?

0

2 Answers 2

2

JSX converts component types that start with a capital letter into React.createElement calls to that type:

<App/> // => React.createElement(App);

However, it converts component types that start with lowercase letters into DOM nodes (by passing it as a string instead of a reference):

<connectedApp/> // => React.createElement("connectedApp");

In fact, if you look at the DOM via your browser's inspector, you'll likely see

<connectedApp data-reactid=".0"></connectedApp>

Try capitalizing connectedApp:

var ConnectedApp = connect(...)(App);

// ...

React.render(<ConnectedApp/>, target);
Sign up to request clarification or add additional context in comments.

1 Comment

That's brutal (I've been messing around for hours trying to understand what I've done wrong with my app!)
0

You are not passing a valid ReactElement to your second render method.

The first <App/> component is valid an therefor is being rendered as a DOM node.

The second <connectedApp/> however is not a ReactElement. So it won't be rendered at all. It is just a function. var connectedApp = connect(function(s) { debugger })(App);

Taken from the API from REDUX the typical use of the connect function is as follows:

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(App)

with the arguments:

[mapStateToProps(state, [ownProps]): stateProps] (Function)

The App component subscribes to the redux store updates, and this function is always called if the component updates. The return of this function should be a object.

[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function)

As object, every function inside will be recognized as a valid action creator

You don't need to pass the connect to a render method, just subscribe your App to the REDUX store.

So taken from the official REDUX page, this is how you set up the subscription:

import { React } from 'react'
import * as actionCreators from './actionCreators'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) }
}

class TodoApp extends React.Component {
  //your App
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.