I try to add more props to existing list i am able to fire dispatch action but reducer doesn't get trigger
i have my headercontainer.js file like
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { fetchAccount } from 'actions/account'
import { getAccount } from 'reducers/account'
import { fetchCart } from 'actions/cart'
import { getCart } from 'reducers/cart'
//import * as cls from 'actions/cls'
import { getReadmore } from 'reducers/cls'
import * as cls from 'actions/cls'
import { fetchAuthenticityToken } from 'actions/authenticityToken'
import { getAuthenticityToken } from 'reducers/authenticityToken'
import Header from 'components/Header'
class HeaderContainer extends Component {
static propTypes = {
account: PropTypes.object,
authenticityToken: PropTypes.object,
cart: PropTypes.object,
dispatch: PropTypes.func
}
componentDidMount() {
if (typeof document !== 'undefined') {
if (!this.props.account.isFetching) {
this.props.dispatch(fetchAccount())
}
if (!this.props.authenticityToken.isFetching) {
this.props.dispatch(fetchAuthenticityToken())
}
if (!this.props.cart.isFetching) {
this.props.dispatch(fetchCart())
}
}
}
constructor(props) {
super(props);
this.state = {classToSend: true };
}
stateToRender(){
(this.state.classToSend) ? this.setState({classToSend: false}) : this.setState({classToSend: true});
}
onClickHandler(){
this.stateToRender();
let action = cls.readMore(this.state.classToSend)
this.props.dispatch(action)
// this.props.readMore(this.state.classToSend);
}
render() {
const { account, cart, authenticityToken } = this.props
if(!account || !cart) {
return false
}
return (
<div id ="cvb">
<div id="toggle-nav" className={this.state.toggleClass?'visible-xs nav-open':'visible-xs'} onClick={() => this.onClickHandler()} >
<span data-action="toggle-nav" className="action mt-menu-label">
<span className="mt-menu-bread mt-menu-bread-top">
<span className="mt-menu-bread-crust mt-menu-bread-crust-top"></span>
</span>
<span className="mt-menu-bread mt-menu-bread-middle">
<span className="mt-menu-bread-crust mt-menu-bread-crust-middle"></span>
</span>
<span className="mt-menu-bread mt-menu-bread-bottom">
<span className="mt-menu-bread-crust mt-menu-bread-crust-bottom"></span>
</span>
</span>
</div>
<Header account={account} cart={cart} />
</div>
)
}
}
const mapStateToProps = (state) => {
return {
account: getAccount(state),
cart: getCart(state),
classToSend: getReadmore(state),
authenticityToken: getAuthenticityToken(state)
}
}
export default connect(mapStateToProps)(HeaderContainer)
My cls.js reducer
export function getReadmore(state) {
console.log(state.readMore1)
console.log("are yar")
return state.readMore1
}
export function readMore1 (state="", action) {
console.log(action.type)
switch(action.type){
case READ_MORE:
return action.payload;
}
return state;
}
cls.js Action
export function readMore(class_something) {
const READ_MORE = 'READ_MORE';
console.log("--------------------------")
console.log(class_something)
return {
type: READ_MORE,
payload: class_something
};
}
Though i am able to call action cls.js file but reducer not getting trigger
can anyone help me to get out of this trouble.
My edits
my index.js in reducer folder
import { combineReducers } from 'redux'
import { reducer as form } from 'redux-form'
import { routerReducer } from 'react-router-redux'
import { currency } from './currency'
import { cart } from './cart'
import { account } from './account'
import { alerts } from './alerts'
import { login } from './login'
import { authenticityToken } from './authenticityToken'
import { products } from './products'
import { product } from './product'
const routing = routerReducer
const rootReducer = combineReducers({
form,
routing,
currency,
cart,
cls,
account,
alerts,
authenticityToken,
login,
products,
product
})
export default rootReducer
Your case in your reducer file should be "READ_MORE" (with quotations) not READ_MORE (without quotations).
Related
How can I access the field values in a parent component of a redux-form component?
I'm not sure if it's caused by typescript, but before I started using typescript, I was able to access the form values through mapStateToProps just like how I have it currently. I've been trying to figure out what was different to my previous implementation but the only difference would be the versions of the npm dependencies and the addition of typescript.
LoginPage.tsx
import LoginForm from 'components/Forms/LoginForm'
import Layout from 'components/Layout'
import { StatusCodes } from 'lib/enums/statusCodes'
import { storeAuthToken } from 'lib/helpers/auth'
import { NextPage } from 'next'
import Router from 'next/router'
import React from 'react'
import { connect, DispatchProp } from 'react-redux'
import { FormInstance } from 'redux-form'
interface IProps {
login: FormInstance<IFormData, IFormProps>
}
interface IState {
errorMessage?: string,
processing: boolean
}
interface IRootState {
form: IProps
}
export interface IFormData {
username?: string,
password?: string
}
export interface IFormProps {
contactId?: string,
errorMessage?: string,
fieldValues: Partial<IFormData>,
processing: boolean
}
class LoginPage extends React.Component<NextPage & DispatchProp & IProps, IState> {
state = {
errorMessage: undefined,
processing: false
}
setErrorMessage = (message: string) => {
this.setState({
errorMessage: message,
processing: false
})
}
handleSubmit = async (values: IFormData) => {
if (values && values.username && values.password) {
this.setState({
errorMessage: undefined,
processing: true
})
try {
const { dispatch } = this.props
await storeAuthToken(dispatch, values.username, values.password)
Router.push('/')
} catch (error) {
if (error === StatusCodes.BAD_REQUEST) {
this.setErrorMessage("Sorry, you have entered incorrect details. Please try again.")
} else {
this.setErrorMessage("Sorry, there was an issue trying to log you in")
}
}
}
}
render() {
const { login } = this.props
const { processing } = this.state
return (
<Layout title="Login">
<div className="form-wrapper full">
<LoginForm processing={processing} onSubmit={this.handleSubmit} fieldValues={login.values} />
</div>
</Layout>
)
}
}
const mapStateToProps = ({ form: { login } }: IRootState) => ({ login })
export default connect(mapStateToProps)(LoginPage)
LoginForm.tsx
import Link from 'next/link'
import React from 'react'
import { Field, InjectedFormProps, reduxForm } from 'redux-form'
import FormButton from 'components/Forms/FormButton'
import Input from 'components/Fields/Input'
import { validateRequired } from 'lib/helpers/validators'
import { IFormProps, IFormData } from 'pages/login'
class LoginForm extends React.Component<IFormProps & InjectedFormProps<IFormData, IFormProps>> {
render() {
const { contactId, errorMessage, fieldValues, handleSubmit, processing } = this.props
return (
<form id="login" onSubmit={handleSubmit} >
<h1>Sign in</h1>
<fieldset>
<div className="fields">
{
!contactId
? <Field name="username" type="text" component={Input} label="Username" validate={validateRequired} />
: <Field name="username" type="email" component={Input} label="Email" validate={validateRequired} />
}
</div>
<div className="fields">
<Field name="password" type="password" component={Input} label="Password" validate={validateRequired} />
</div>
</fieldset>
{ errorMessage && <p className="error-message">{errorMessage}</p> }
<div className="form-bottom">
<Link href="/"/*{`/forgot-password${fields.email ? `?email=${encodeURIComponent(fields.email)}` : ''}`}*/>
<a className="inline">Forgotten your password?</a>
</Link>
<FormButton loading={processing}>
Login
</FormButton>
</div>
</form>
)
}
}
export default reduxForm<{}, IFormProps>({ form: 'login' })(LoginForm)
Here is my redux store file incase if that is coded incorrectly
import { createWrapper, HYDRATE, MakeStore } from 'next-redux-wrapper'
import { AnyAction, applyMiddleware, combineReducers, createStore, Reducer } from 'redux'
import { reducer as formReducer } from 'redux-form'
import thunkMiddleware, { ThunkMiddleware } from 'redux-thunk'
import authReducer, { AuthState } from './auth/reducer'
import contactReducer, { ContactState } from './contact/reducer'
import initialState from './initialState'
export interface State {
auth: AuthState
contact: ContactState
}
const bindMiddleware = (middleware: [ThunkMiddleware]) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension')
return composeWithDevTools(applyMiddleware(...middleware))
}
return applyMiddleware(...middleware)
}
const combinedReducer = combineReducers({
auth: authReducer,
contact: contactReducer,
form: formReducer
})
const reducer: Reducer = (state: State, action: AnyAction) => {
if (action.type === HYDRATE) {
const nextState: Reducer = {
...state,
...action.payload
}
return nextState
} else {
return combinedReducer
}
}
const makeStore: MakeStore<State> = () => createStore(reducer, initialState, bindMiddleware([thunkMiddleware]))
export const wrapper = createWrapper<State>(makeStore/*, { debug: true }*/)
It seems like I missed out a key in the IApplicationState interface and as mentioned by #cbr, the parameters state and action needed to be passed to combinedReducer even though it doesn't directly take any.
Additionally it didn't like when the nextState constant had the type Reducer, so I have changed that to CombinedState<State> as well
The changed code looks like this
import { createWrapper, HYDRATE, MakeStore } from 'next-redux-wrapper'
import { AnyAction, applyMiddleware, combineReducers, createStore, Reducer } from 'redux'
import { reducer as formReducer } from 'redux-form'
import thunkMiddleware, { ThunkMiddleware } from 'redux-thunk'
import authReducer, { AuthState } from './auth/reducer'
import contactReducer, { ContactState } from './contact/reducer'
import initialState from './initialState'
export interface State {
auth: AuthState
contact: ContactState,
form: FormStateMap
}
const bindMiddleware = (middleware: [ThunkMiddleware]) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension')
return composeWithDevTools(applyMiddleware(...middleware))
}
return applyMiddleware(...middleware)
}
const combinedReducer = combineReducers({
auth: authReducer,
contact: contactReducer,
form: formReducer
})
const reducer: Reducer = (state: State, action: AnyAction) => {
if (action.type === HYDRATE) {
const nextState: CombinedState<State> = {
...state,
...action.payload
}
return nextState
} else {
return combinedReducer(state, action)
}
}
const makeStore: MakeStore<State> = () => createStore(reducer, initialState, bindMiddleware([thunkMiddleware]))
export const wrapper = createWrapper<State>(makeStore)
i'm another guy with the same question; Sorry, but I could not see yet my error.I'm suspecting is something about mutation, but I tried (almost) everything, getting mad. My component is not updating when I add stuff to my store, it seems is rendering just for once (first time)
I was trying with lifecycles but nothing
ACTION
export default async function getJoke() {
let jk = await axios.get('https://jokeapi.p.rapidapi.com/category/any' ,{ headers :{
'x-rapidapi-host' : 'jokeapi.p.rapidapi.com',
'x-rapidapi-key' : "***********************" }} );
let joke;
if(jk.data.type === 'single') {
joke = jk.data.joke
} else {
joke = { setup : jk.data.setup,
delivery : jk.data.delivery}
}
let getjoke = {
type : 'GETJOKE',
joke
}
store.dispatch(getjoke) ;
}
REDUCER
let initialState = { jokes : [ ] };
function joke (state = initialState, action) {
switch (action.type) {
case 'GETJOKE' : return {...state,
jokes :[...state.jokes, {jokes: action.joke}]
} ;
default : return state;
}
}
export default joke;
REDUCER-INDEX
import { combineReducers } from 'redux';
import joke from './joke'
export default combineReducers ({
joke
})
STORE
import { createStore } from 'redux';
import Combined from './reducer';
export default createStore(Combined);
COMPONENT
import React from 'react';
import BotJoke from './btnJoke';
import {connect} from 'react-redux';
import store from '../store'
class joke extends React.Component {
constructor(props) {
super(props);
this.state = {
jokes : props.jokes
}
console.log('MENDA',this.state.jokes);
}
componentDidMount() {
console.log('willdisssd receive props');
/* this.setState({jokes : [...this.state.jokes, nextProps]})
*/
}
componentWillMount(){
console.log('will mount',this.state.jokes);
console.log('Entra');
console.log('NEXT PROPS');
}
render() {
return (
<div>
<BotJoke/>
{ this.state.jokes !== undefined ? <h1>Hay bromas</h1>: <h1>NO HAY BROMAS</h1> }
</div>
)
} }
function mapStateToProps (state) {
console.log('STorE', store.getState());
return {
jokes : state.jokes
}
}
let connection = connect(mapStateToProps)(joke);
export default connection;
What you are doing is an anti pattern, using the props to setState though you can just use props directly instead.
Use this.props.jokes everywhere in your component, it should work. Let me know.
EDIT:
Assuming you want the jokes to be an array:
REDUCER
let initialState = { jokes : [ ] };
function joke (state = initialState, action) {
switch (action.type) {
case 'GETJOKE' : return {...state,
jokes :[...state.jokes, action.joke]
} ;
default : return state;
}
}
export default joke;
REDUCER-INDEX
import { combineReducers } from 'redux';
import joke from './joke'
export default combineReducers ({
joke
})
STORE
import { createStore } from 'redux';
import Combined from './reducer';
export default createStore(Combined);
COMPONENT
import React from 'react';
import BotJoke from './btnJoke';
import {connect} from 'react-redux';
import store from '../store'
const joke = (props) => {
const length = props.jokes.length
return (
<div>
<BotJoke/>
{ length !== 0 ? <h1>{JSON.stringify(props.jokes[length-1])}</h1>: <h1>NO HAY BROMAS</h1> }
</div>
)
}
function mapStateToProps (state) {
console.log('STorE', store.getState());
return {
jokes : state.jokes
}
}
let connection = connect(mapStateToProps)(joke);
export default connection;
I have component App which render its children and Header component. I use Preloader from react-loader repo which takes bool loaded and render preloader or page in depended from bool. When App componentWillMount, data fetch via actionCreators, action use redux-api-middleware, then when execute render in App, Header fetch data via actionCreator boundGetPhotos which execute recursively look PHOTOS_GET_SUCCESS in console screenshot here i log action.type in my fetchingMiddleware . All actions pass from my middleware fetchingMiddleware look belowe. Which can be reasons of recursive behavior why it execute again and again and how i can solve it
App
import React, { Component, PropTypes } from 'react';
import Counterpart from 'counterpart';
import { connect } from 'react-redux';
import Loader from 'react-loader';
import { bindActionCreators } from 'redux';
import { getFriends, getMessages } from '../data/Data.Actions';
import { getUsers } from '../users/Users.Actions';
import Header from './Header';
class App extends Component {
componentWillMount() {
const { boundGetFriends, boundGetMessages, boundGetUsers } = this.props;
boundGetFriends();
boundGetMessages();
boundGetUsers();
}
render() {
const { children, fetching } = this.props;
return (
<Loader loaded={!fetching.size}>
<div>
<Header/>
{children}
</div>
</Loader>
);
}
}
App.propTypes = {
boundGetUsers: PropTypes.func,
boundGetMessages: PropTypes.func,
boundGetFriends: PropTypes.func,
fetching: PropTypes.array
};
export default connect((store) => {
return {
fetching: store.fetching
};
}, (dispatch) => {
return {
boundGetUsers: bindActionCreators(getUsers, dispatch),
boundGetFriends: bindActionCreators(getMessages, dispatch),
boundGetMessages: bindActionCreators(getFriends, dispatch)
};
})(App);
Header
import React, { Component, PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';
import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { getPhotos } from '../user/User.Actions';
class Header extends Component {
componentWillMount() {
const { boundGetPhotos } = this.props;
boundGetPhotos();
}
render() {
return (
<Navbar fluid collapseOnSelect>
<Navbar.Brand>
MyProject
</Navbar.Brand>
</Navbar>
);
}
}
Header.propTypes = {
boundGetPhotos: PropTypes.func.isRequired
};
export default connect((store) => null, (dispatch) => {
return {
boundGetPhotos: bindActionCreators(getPhotos, dispatch)
};
})(Header);
FetchingMiddleware
import { startFetching, endFetching } from './FetchingMiddleware.Actions';
export default store => next => action => {
console.log(action.type);
if (typeof action !== 'function' && action.type.search(/REQUEST/) !== -1) {
store.dispatch(startFetching());
}
if (typeof action !== 'function' && action.type.search(/SUCCESS|FAILURE/) !== -1) {
store.dispatch(endFetching());
}
next(action);
};
FetchingMiddlewareReducers
import Immutable from 'immutable';
import { END_FETCHING, START_FETCHING, RESET_FETCHING } from './FetchingMiddleware.Actions';
import createReducer from '../utils/utils';
function addFetching(state, action) {
return state.push(true);
}
function removeFetching(state, action) {
return state.pop();
}
function resetFetching(state, action) {
return Immutable.List();
}
export default createReducer({
[END_FETCHING]: removeFetching,
[START_FETCHING]: addFetching,
[RESET_FETCHING]: resetFetching
}, Immutable.List());
FetchingMiddlewareActions
export const END_FETCHING = 'END_FETCHING';
export const START_FETCHING = 'START_FETCHING';
export const RESET_FETCHING = 'RESET_FETCHING';
export function endFetching() {
return {
type: END_FETCHING
};
}
export function startFetching() {
return {
type: START_FETCHING
};
}
export function resetFetching() {
return {
type: RESET_FETCHING
};
}
getPhotos
import { CALL_API } from 'redux-api-middleware';
export const PHOTOS_GET_SUCCESS = 'PHOTOS_GET_SUCCESS';
export function getPhotos() {
return {
[CALL_API]: {
endpoint: '/photos',
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
types: ['REQUESTPHOTOS', PHOTOS_GET_SUCCESS, 'FAILURE']
}
};
}
Your <Header /> component should be a pure component that knows nothing about your state container (Redux) or dispatch.
Using the approach you have here would litter your component tree with 'connect' and add awareness of Redux to all of your components. This is bad practice in terms of scalability - what if you wanted to replace Redux with another state container?.
I would recommend that all state and actions should be bound to props and passed down the tree into your components such as the <Header /> component.
This should also resolve the issues you are having.
App
import React, { Component, PropTypes } from 'react';
import Counterpart from 'counterpart';
import { connect } from 'react-redux';
import Loader from 'react-loader';
import { getMasterDataSchema, getMasterDataData } from '../masterdata/MasterData.Actions';
import { getQuestionnaireSchema } from '../questionnaireschema/QuestionnaireSchema.Actions';
import Header from './Header';
class App extends Component {
componentWillMount() {
const {
GetMasterDataData,
GetMasterDataSchema,
GetQuestionnaireSchema
} = this.props;
GetMasterDataData();
GetMasterDataSchema();
GetQuestionnaireSchema();
}
render() {
const { children, fetching, GetPrincipal } = this.props;
return (
<Loader loaded={!fetching.size}>
<div>
<Header GetPrincipal={GetPrincipal} />
{children}
</div>
</Loader>
);
}
}
App.propTypes = {
GetPrincipal: PropTypes.func,
GetQuestionnaireSchema: PropTypes.func,
GetMasterDataSchema: PropTypes.func,
GetMasterDataData: PropTypes.func,
fetching: PropTypes.array
};
export default connect(({ fetching }) => ({
fetching
}), {
GetPrincipal,
GetQuestionnaireSchema,
GetMasterDataData,
GetMasterDataSchema,
})(App);
Header
import React, { Component, PropTypes } from 'react';
import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
export default class Header extends Component {
componentWillMount() {
const { GetPrincipal } = this.props;
GetPrincipal();
}
render() {
return (
<Navbar fluid collapseOnSelect>
<Navbar.Brand>
EMS
</Navbar.Brand>
</Navbar>
);
}
}
Header.propTypes = {
GetPrincipal: PropTypes.func.isRequired
};
I have been trying to learn to This is a simple login, logout app using Redux. On pressing the Login Button from Display.js, the login_action function should be called. But an error is showing with title Cannot read property login_action of undefined. I tried logging the props in Display.js and I am able to see the functions in the logs but somehow the functions aren't being called. What is it that I'm missing or unable to find out?
Basic App :
/* App.js */
import React, {Component} from 'react';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import * as reducers from './reducers';
import SceneContainer from './containers/SceneContainer';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const reducer = combineReducers(reducers);
const store = createStoreWithMiddleware(reducer);
export default class App extends Component {
render() {
return (
<Provider store={store}>
<SceneContainer />
</Provider>
);
}
}
Container:
/* containers/SceneContainer.js */
'use strict';
import React, {Component, PropTypes} from 'react';
import Display from '../components/display';
import * as loginActions from '../actions/';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
class SceneContainer extends Component {
constructor(props) {
super(props);
}
render() {
const {actions} = this.props;
console.log(actions);
return (
<Display {...actions}/>
);
}
}
SceneContainer.propTypes = {
user: PropTypes.object.isRequired,
actions: PropTypes.object.isRequired
};
function mapStateToProps(state) {
return {user: state.auth.user};
}
function mapDispatchToProps(dispatch) {
console.log(loginActions);
return {
actions: bindActionCreators(loginActions, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SceneContainer);
Component :
/* components/display.js */
import React, {Component, PropTypes} from 'react';
import {
View,
Text,
StyleSheet,
TouchableHighlight,
} from 'react-native';
class Display extends Component {
constructor(props) {
super(props);
console.log(props.login_action);
}
onLoginPress() {
this.props.login_action({
username: 'ranat',
password: 'password'
});
}
onLogoutPress() {
this.props.logout_action();
}
render() {
return (
<View>
<TouchableHighlight onPress={this.onLoginPress}>
<Text>Login</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.onLogoutPress}>
<Text>Logout</Text>
</TouchableHighlight>
</View>
);
}
}
Display.propTypes = {
logout_action: PropTypes.func.isRequired,
login_action: PropTypes.func.isRequired
};
export default Display;
Actions file :
/* actions/index.js */
import {LOGIN_ACTION, LOGOUT_ACTION, LOGIN_SUCCESS, LOGIN_FAILURE} from './actionTypes';
export var login_action = (userCredentials) => {
if(userCredentials.username === 'ranat' && userCredentials.password === 'password') {
return {
type: LOGIN_ACTION,
value: LOGIN_SUCCESS,
};
}
else {
return {
type: LOGIN_ACTION,
value: LOGIN_FAILURE,
};
}
};
export var logout_action = () => {
return {
type: LOGOUT_ACTION,
}
};
Reducers :
/* reducers/login.js */
import {LOGIN_ACTION, LOGOUT_ACTION, LOGIN_SUCCESS, LOGIN_FAILURE} from '../actions/actionTypes'
let cloneObject = (obj) => {
if(obj)
return JSON.parse(JSON.stringify(obj));
else
return {};
}
const initialState = {
user: {
loggedIn: false,
},
};
const auth = (state = initialState, action = {}) => {
switch(action.type) {
case LOGIN_ACTION: {
if(action.value === LOGIN_SUCCESS) {
return {
...state,
user: {
loggedIn: true
}
};
}else {
return {
...state,
user: {
loggedIn: false
}
};
}
}
case LOGOUT_ACTION: {
if(action.value === LOGIN_SUCCESS) {
return {
...state,
user: {
loggedIn: false
}
};
}else {
return state;
}
}
default: {
return state || initialState;
}
}
}
export default auth;
/* reducers/index.js */
import { combineReducers } from 'redux';
import auth from './login';
export {
auth,
};
Change onPress={this.onLoginPress} to onPress={this.onLoginPress.bind(this}.
Do the same for onPress={this.onLogoutPress} also.
When I click the DIV in Home container, I have confirmed the set function is called (I see the console log)
teamReducer function is never called. Maybe bindActionCreators should be used differently? How can i have my action creator send action to reducer to update the league store?
// teamReducer.js
export function teamReducer(state = initialState, action){
switch (action.type) {
case 'SET_TEAM':
return {
...state,
called: true
};
default:
return state;
}
};
// reducers/index.js
import { combineReducers } from 'redux';
import { routeReducer } from 'redux-simple-router';
import { teamReducer } from './teamReducer';
const rootReducer = combineReducers({
routing: routeReducer,
league: teamReducer,
});
export default rootReducer;
// actions/setTeam.js
export function setTeam(team, position) {
console.log(team, position);
return {
type: 'SET_TEAM',
team,
position
};
}
}
// Home.js
import React, { PropTypes, Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import {setTeam } from '../../actions/teams';
const mapStateToProps = ({league}) => {
return {
called: league.called
};
};
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
setTeam,
}, dispatch);
};
#connect(mapStateToProps, mapDispatchToProps)
export class Home extends Component {
constructor(props) {
super(props);
}
render() {
const {set} = this.props.setTeam
return <div onClick={set} />
}
}
The issue in the render function. You use destructuring assignment wrong.
render() {
const {set} = this.props.setTeam;
return <div onClick={set} />
}
This assignment is the same as in the following code:
const set = this.props.setTeam.set;
But setTeam is a function and doesn't have set property. The correct code is:
render() {
const {setTeam} = this.props;
return <div onClick={setTeam} />
}