Nick Borisenko Nick Borisenko - 3 months ago 9
React JSX Question

Connecting actions and states to props in React Container

I'm learning react/redux and I'm trying to create a simple application that just changes the state of a prop

onClick
. I get an error when trying to connect my states and actions to props in my presentation component via the react-redux
connect()
function and the
mapStateToProps
&
mapDispatchtoProps
functions. When I run my app, the browser console reads out an error saying that the props I declared in my presentational component were not specified, so I'm assuming that means that the error lies in my container. I've read up on the documentation and reviewed several example applications, but I still don't see where I'm going wrong.

LoginContainer.js
code:

import { connect } from 'react-redux'
import { submit } from '../modules/login'
import Login from 'components/Login'

const mapDispatchtoProps = {
submit
}

const mapStateToProps = (state) => ({
submitted: state.submitted
})

export default connect(mapStateToProps, mapDispatchtoProps)(Login)


I import the required function
connect()
, the function
submit
, which is the action that triggers the reducer (which I already connected to the store),and the component I want to connect to. I then connect the
submit
prop to the redux action, and connect the
submitted
prop to the state, which is just used a boolean.

My simplified login component code (just in case):

import React from 'react'

export const Login = (props) => (
<div>
<button type="button" onClick={props.submit}>Submit</button>
<p>{props.submitted ? "true" : "false"}</p>
</div>
)

Login.propTypes = {
submit: React.PropTypes.func.isRequired,
submitted: React.PropTypes.bool.isRequired
}

export default Login


Let me know if I should include the
module/login
file I referenced, which contains the reducer functions and actions. I opted not to include it here as it doesn't seem involved in the error.

Edit: In response to @anoop's comment, I am importing the login component into the login container code. The component itself is inserted into a
HomeView
component, so the login component is never explicitly referenced in the routes at all. The only other places that these files are referenced is when I inject the reducer to the store.

My injectReducer code:

import { injectReducer } from '../../store/reducers'

export default (store) => ({
path: '',
getComponent (nextState, cb) {
require.ensure([], (require) => {
const Login = require('./containers/LoginContainer').default
const reducer = require('./modules/login').default
injectReducer(store, { key: 'login', reducer })
cb(null, Login)
}, 'login')
}
})


HomeView
component code:

import React from 'react'
import Login from '../../../components/Login/Login.js'

export const HomeView = () => (
<div>
<Login />
</div>
)

export default HomeView


Simplified
createRoutes
file:

import CoreLayout from '../layouts/CoreLayout/CoreLayout'
import NotFound from './NotFound'
import Home from './Home'
//import ExampleRoute from './Example'

export const createRoutes = (store) => ({
path: '/',
component: CoreLayout,
indexRoute: Home,
getChildRoutes (location, next) {
require.ensure([], (require) => {
next(null, [
//require('./Example').default(store),
require('./NotFound').default
])
})
}
})

export default createRoutes


After looking at the routing file, I realized that in the
createRoutes
function, I passed in the store as a parameter but never used it in the function. I am using a boilerplate app which initially had a route that passed the
store
value to it. In the code above I commented out the route syntax that was used.

I suppose my question has now evolved to the following: Since the login component is nested inside the
HomeView
component, do I need to pass the store to the Home route? If so, how do I pass it to the default
Home
route as in the commented
exampleRoute
above?

Answer

My problem was that I was importing the component instead of the container in my HomeView. The corrected code in that file is as follows:

import React from 'react'
import classes from './HomeView.scss'
const Login = require('../../Login/containers/LoginContainer').default

export const HomeView = () => (
  <div>
    <Login />
  </div>
)

export default HomeView
Comments