Action creator not called - reactjs

Im not 100% sure if it is working correct, but it does noet give the result of the video course that I followed.
The renderPosts is just suppose to render the list, but instead it get a blank array the first time round. and when mapStateToProps is called the second time, the array is filled with the expected values.
it is as if the first time mapStateToProps is invoked, it did not pass through the action creator first or something.
COMPONENT
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '../actions/index';
import { Link } from 'react-router';
class PostsIndex extends Component {
componentWillMount() {
console.log("componentWillMount");
this.props.fetchPosts();
}
renderPosts() {
// console.log("renderPosts - this.props.posts",this.props.posts);
if(this.props.posts){
return this.props.posts.map((post) => {
return (
<li className="list-group-itme" key="{post.id}">
<span className="pull-xs-right">{post.catagories}</span>
<strong>{post.title}</strong>
</li>
);
});
}
}
render() {
return (
<div>
<div className="text-xs-right">
<Link to="/posts/new" className="btn btn-primary">
Add New Post
</Link>
</div>
<h3>Posts</h3>
<ul className="list-group">
{this.renderPosts()}
</ul>
</div>
);
}
}
function mapStateToProps(state) {
console.log("mapStateToProps",state.posts);
return {posts: state.posts.all}
}
export default connect(mapStateToProps, {fetchPosts})(PostsIndex);
ACTION
import axios from 'axios';
export const FETCH_POSTS = 'FETCH_POSTS';
export const CREATE_POST = 'CREATE_POST';
const ROOT_URL = 'http://reduxblog.herokuapp.com/api';
const API_KEY = '?key=qwerty123';
export function fetchPosts(){
const request = axios.get(`${ROOT_URL}/posts${API_KEY}`);
return {
type: FETCH_POSTS,
payload: request
};
}
export function createPost(props) {
const request = axios.post(`${ROOT_URL}/posts${API_KEY}`, props);
return{
type: CREATE_POST,
payload: request
}
}
REDUCER
import { FETCH_POSTS } from '../actions/index';
const INITIAL_STATE = { postsList:[], post:null };
export default function(state = INITIAL_STATE, action){
console.log("action.type",action.type);
switch (action.type) {
case FETCH_POSTS:
return {...state, postsList: action.payload.data};
default:
return state;
}
}
mapStateToProps is called twice. on the initial call the array is empty. on the second call I have my ten posts inside the array.
Problem is that it seems to want to render the first array and ignores the second
I have put an consol.log in the
renderPosts
and
mapStateToProps
and it renders as follows.
Console
any Ideas?

I think the error is coming from the way you handle the Promise. The first time you see the mapStateToProps in the console you can see you have no data so this is PENDING, the second is when it's FULFILLED. You need to find a way to handle this.
Example but not the best, I think you can just change you if statement.
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '../actions/index';
import { Link } from 'react-router';
class PostsIndex extends Component {
componentWillMount() {
console.log("componentWillMount");
this.props.fetchPosts();
}
renderPosts() {
return this.props.posts.map((post) => {
return (
<li className="list-group-itme" key="{post.id}">
<span className="pull-xs-right">{post.catagories}</span>
<strong>{post.title}</strong>
</li>
);
});
}
render() {
return (
<div>
<div className="text-xs-right">
<Link to="/posts/new" className="btn btn-primary">
Add New Post
</Link>
</div>
<h3>Posts</h3>
<ul className="list-group">
{this.props.posts !== [] this.renderPosts() : <h1>Loading...</h1>}
</ul>
</div>
);
}
}
function mapStateToProps(state) {
console.log("mapStateToProps",state.posts);
return {posts: state.posts.all}
}
export default connect(mapStateToProps, {fetchPosts})(PostsIndex);
The second one should be by changing the way you do the promise. A good library is redux-promise-middleware
This is a example of my app what I did.
Actions
export const reqAllGames = games => {
const promise = new Promise((resolve, reject) => {
request
.get(`${config.ROOT_URL}/${config.API_KEY}`)
.end((err, res) => {
if (err) {
reject(err);
} else {
resolve(res.body.top);
}
});
});
return {
type: types.RECEIVE_ALL_GAMES,
payload: promise
};
};
Reducer
import * as types from "../constants/";
const gameReducer = (games = { isFetched: false }, action) => {
switch (action.type) {
case `${types.RECEIVE_ALL_GAMES}_PENDING`:
return {};
case `${types.RECEIVE_ALL_GAMES}_FULFILLED`:
return {
games: action.payload,
err: null,
isFetched: true
};
case `${types.RECEIVE_ALL_GAMES}_REJECTED`:
return {
games: null,
err: action.payload,
isFetched: true
};
default:
return games;
}
};
export default gameReducer;
Component
const Games = ({ games, err, isFetched }) => {
if (!isFetched) {
return <LoadingCircular />;
}
else if (err === null) {
return (
<div>
<GamesList games={games} />
</div>
);
} else {
return <h1>Games not find!</h1>;
}
};
const mapStateToProps = (state) => state.games;
export default connect(mapStateToProps)(Games);
If you using react-router you can use the onEnter api and do the actions right here. With that you know your component gonna get the post. A good tutorial is this one from RallyCoding https://www.youtube.com/watch?v=JicUNpwLzLY
Hope that can help you

https://www.udemy.com/react-redux/learn/v4/questions/1693796
In your reducer you're assigning the list of posts to the key postsList.
case FETCH_POSTS:
return {...state, postsList: action.payload.data};
We can confirm that they are properly being assumed to postsList by looking at the mapStateToProps console log you have in your screenshot.
Your mapStateToProps, however, is looking at the property state.posts.all
return {posts: state.posts.all}
The list of posts are not assigned to the all property, they are assigned to the postsList property. This is why you don't see the updated list of posts in your component. You'll need to update either the property the reducer is placing the list of posts on or update your mapStateToProps to pull the list of posts from the correct property.
-Stephen Grider

Related

Redux mapStateToProps state in components

I get my action called in Redux Dev Tools and even the new state, but in the actual Component props is undefined.
The component:
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { getPromos } from '../../actions/promo';
import PropTypes from 'prop-types';
const Landing = ({ getPromos, data }) => {
useEffect(() => {
getPromos();
console.log(data) // ==>> "UNDEFINED"
}, []);
return (
<div>
<section className='landing'>
<div className='dark-overlay'>
<div className='landing-inner'>
<h1 className='x-large'> Developer Connector </h1>
<p className='lead'>
Create a developer profile/portfolio, share posts and get help
from other developers
</p>
<div className='buttons'>
<Link to='/register' className='btn btn-primary'>
Sign Up
</Link>
<Link to='/login' className='btn btn-light'>
Login
</Link>
</div>
</div>
</div>
</section>
</div>
);
};
Landing.propTypes = {
getPromos: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
data: state.data
});
export default connect(
mapStateToProps,
{ getPromos }
)(Landing);
Actions:
import axios from 'axios';
import { setAlert } from './alert';
import { GET_PROMOS, REGISTER_FAIL } from './types';
export const getPromos = () => async dispatch => {
try {
const res = await axios.get('/api/promo');
dispatch({
type: GET_PROMOS,
payload: res.data
});
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({ type: REGISTER_FAIL });
}
};
And reducer:
import { GET_PROMOS } from '../actions/types';
const initialState = {
data: null,
title: ''
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_PROMOS:
return { ...state, data: payload };
default:
return state;
}
}
Like I said, in Redux Dev Tools I get my desired output. But for some reason I cant get to echo this state in the component. What im getting wrong? Can it be something about the hooks?
Thanks !
First thing that jumps at me is that you have a naming conflict with the getPromos in your component, it's defined in the imports as getPromos then it's destructured in the component as { getPromos } as well. I'm surprised you didn't get an error there for naming conflicts.
You will want to NOT destructure getPromos in the component and instead call it as (props) => { props.getPromos } to actually call the connected action creator instead of the unconnected one.
Second, Is that reducer the main root reducer? or is it nested in the root reducer? if the latter is true then in your mapStateToProps the data prop should be one level deeper, as in state: state.rootLevelState.data
(sorry can't ask questions in the comments due to reputation < 50)
enter image description here
Here's a screenshot of the redux dev tools

Redux api calling

I'm wanting to update my trending array with the results calling the tmdb api. I'm not sure if im going about this the wrong way with calling the api or if im messing up somewhere else along the way. So far I've really been going in circles with what ive tried. Repeating the same things and not coming to a real solution. Havent been able to find another question similar to mine.
my actions
export const getTrending = url => dispatch => {
console.log("trending action");
axios.get(url).then(res =>
dispatch({
type: "TRENDING",
payload: res.data
})
);
};
my reducer
const INITIAL_STATE = {
results: [],
trending: []
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case "SEARCH_INFO":
return {
results: [action.payload]
};
case "TRENDING":
return { trending: action.payload };
default:
return state;
}
};
and my component im trying to get the results from
import React, { Component } from "react";
import Trending from "./Treding";
import "../App.css";
import { getTrending } from "../actions/index";
import { connect } from "react-redux";
export class Sidebar extends Component {
componentDidMount = () => {
const proxy = `https://cors-anywhere.herokuapp.com/`;
getTrending(`${proxy}https://api.themoviedb.org/3/trending/all/day?api_key=53fbbb11b66907711709a6f1e90fc884
`);
};
render() {
return (
<div>
<h3 className="trending">Trending</h3>
{
this.props.trending ? (
<Trending movies={this.props.trending} />
) : (
<div>Loading</div>
)}
</div>
);
}
}
const mapStateToProps = state => {
return {
trending: state.trending
};
};
export default connect(mapStateToProps)(Sidebar);
Since you are directly calling the getTrending without passing it to connect method, it might be the issue.
Instead that you can pass getTrending to connect method so it can be available as props in the component. After that it can be dispatched and it will be handled by redux/ redux-thunk.
export default connect(mapStateToProps, { getTrending })(Sidebar);
And access it as props in the component.
componentDidMount = () => {
// const proxy = `https://cors-anywhere.herokuapp.com/`;
this.props.getTrending(`https://api.themoviedb.org/3/trending/all/day?api_key=53fbbb11b66907711709a6f1e90fc884
`);
};

React with Redux: returns incorrect state object

I have React with Redux and Electron project. I try to save current screen id to redux and get the saved state on next screen. The problem is, that when I use getSettings, the return value should be my saved state:
Object{settings: Object}
but is action's object:
Object{type: "GET_SETTINGS", payload: ""}
When I put console log to reducer_settings.js, it show correct state. So it seems it is something with binding the getSettings method. Thanks for your help
containers/screen_picker.js:
import React, {Component} from 'react';
import Navigation from "../components/navigation";
const {desktopCapturer, ipcRenderer} = require('electron');
import {connect} from 'react-redux';
const domify = require('domify')
import App from '../components/app'
import {bindActionCreators} from 'redux';
import {setSettings, getSettings} from "../actions/index";
class ScreenPicker extends App {
constructor(){
super();
this.showPicker();
}
showPicker(){
ipcRenderer.send('show-picker', { types: ['screen'] });
ipcRenderer.on('get-sources', (event, options) => {
desktopCapturer.getSources(options, (error, sources) => {
if (error) throw error
let sourcesList = document.querySelector('.capturer-list')
for (let source of sources) {
let thumb = source.thumbnail.toDataURL()
if (!thumb) continue
let title = source.name.slice(0, 20)
let item = `<li><img src="${thumb}"><span>${title}</span></li>`
sourcesList.appendChild(domify(item))
}
let links = sourcesList.querySelectorAll('a')
for (let i = 0; i < links.length; ++i) {
let closure = (i) => {
return (e) => {
e.preventDefault()
// ipcRenderer.send('source-id-selected', sources[i].id)
// sourcesList.innerHTML = ''
this.props.setSettings({
screenId: sources[i].id
});
}
}
links[i].onclick = closure(i)
}
})
})
}
render() {
return (
<div className="window-wrapper">
<div className="main-content">
<div className="capturer-container dn">
<div className="cr">
<p className="mbl">Select the window you want to share:</p>
<ul className="capturer-list"></ul>
</div>
</div>
</div>
<Navigation nextRouteUrl="/camera-test" backRouteUrl="/" />
</div>
)
}
}
function mapStateToProps(state){
return {
settings: state.settings
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({setSettings, getSettings}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(ScreenPicker);
containers/camera_test.js
const {ipcRenderer} = require('electron');
import React, {Component} from 'react';
import Navigation from "../components/navigation";
import {connect} from 'react-redux';
import App from '../components/app'
import {bindActionCreators} from 'redux';
import {getSettings} from "../actions/index";
class CameraTest extends App {
constructor(){
super();
}
componentDidMount() {
console.log("settings in camera test start");
console.log(this.props.getSettings());
console.log("settings in camera test end");
ipcRenderer.send('stepWindow:create', { });
}
render() {
return (
<div className="window-wrapper">
<div className="main-content">
CameraTest div
</div>
<Navigation nextRouteUrl="/camera-test" backRouteUrl="/screen-picker" />
</div>
)
}
}
function mapStateToProps(state){
return {
settings: state.settings
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({getSettings}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(CameraTest);
reducers/reducer_settings.js:
import {GET_SETTINGS, SET_SETTINGS} from "../actions/index";
export default function (state = {},action) {
let newState;
switch (action.type){
case GET_SETTINGS:
console.log("reducer GET_SETTINGS");
console.log(state);
return state;
case SET_SETTINGS:
newState = { ...state, ["settings"]: action.payload };
console.log("Start newstate");
console.log(newState);
console.log("End newstate");
return newState;
default:
return state
}
}
actions/index.js
export const SET_SETTINGS = 'SET_SETTINGS';
export const GET_SETTINGS = 'GET_SETTINGS';
export function setSettings(values, callback){
return {
type: SET_SETTINGS,
payload: values
}
}
export function getSettings(){
console.log("actions#getSettings");
return {
type: GET_SETTINGS,
payload: ""
}
}
you dont need the getSetting action creator.
in your component did mount access the settings like this.
componentDidMount() {
console.log("settings in camera test start");
const { settings} = this.props;
console.log(settings);
console.log("settings in camera test end");
ipcRenderer.send('stepWindow:create', { });
}
assuming your object is called settings. normally the object is given the name you are exporting in the reducer. so if you are not able to see an object called settings in props, you need to give your reducer function a name
export default function settings (state = {},action) {
let newState;
switch (action.type){
case GET_SETTINGS:
console.log("reducer GET_SETTINGS");
console.log(state);
return state;
case SET_SETTINGS:
newState = { ...state, ["settings"]: action.payload };
console.log("Start newstate");
console.log(newState);
console.log("End newstate");
return newState;
default:
return state
}
}
EDIT: its mapStateToProps which gives the object name is props.

React / Redux Async not waiting for returned response

First of all my code is working (everything is exported correctly etc ) but it's not waiting for the async return of data.
I'm using redux-thunk for my async middleware
I have an action named async.js
export function itemsHasErrored(bool) {
return {
type: 'ITEMS_HAS_ERRORED',
hasErrored: bool
};
}
export function itemsIsLoading(bool) {
return {
type: 'ITEMS_IS_LOADING',
isLoading: bool
};
}
export function itemsFetchDataSuccess(items) {
return {
type: 'ITEMS_FETCH_DATA_SUCCESS',
items
};
}
export function itemsFetchData(url) {
return (dispatch) => {
dispatch(itemsIsLoading(true));
fetch(url)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
dispatch(itemsIsLoading(false));
return response;
})
.then((response) => response.json())
.then((items) => dispatch(itemsFetchDataSuccess(items)))
.catch(() => dispatch(itemsHasErrored(true)));
};
}
My reducer
export function itemsHasErrored(state = false, action) {
switch (action.type) {
case 'ITEMS_HAS_ERRORED':
return action.hasErrored;
default:
return state;
}
}
export function itemsIsLoading(state = false, action) {
switch (action.type) {
case 'ITEMS_IS_LOADING':
return action.isLoading;
default:
return state;
}
}
export function items(state = [], action) {
switch (action.type) {
case 'ITEMS_FETCH_DATA_SUCCESS':
return action.items;
default:
return state;
}
}
I have a container component, asyncContainer.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux'
import {itemsFetchData} from '../../../actions/async';
import AsyncUI from './asyncUI'
class AsyncContainer extends Component {
componentDidMount() {
this.props.fetchData('http://5826ed963900d612000138bd.mockapi.io/items');
}
render() {
if (this.props.hasErrored) {
return <p>Sorry! There was an error loading the items</p>;
}
if (this.props.isLoading) {
return <p>Loading…</p>;
}
//This fails to wait
return (
<AsyncUI />
);
}
}
AsyncContainer.propTypes = {
fetchData: PropTypes.func.isRequired,
items: PropTypes.array.isRequired,
hasErrored: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired
};
const mapStateToProps = (state) => {
return {
items: state.items,
hasErrored: state.itemsHasErrored,
isLoading: state.itemsIsLoading
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(itemsFetchData(url))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(AsyncContainer);
And finally I have a simple UI component named asyncUI.js written in a functional way
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux'
const AsyncUI = (items) => {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item.label}
</li>
))}
</ul>
);
}
const mapStateToProps = (state) => {
return {
items: state.items
};
};
export default connect(mapStateToProps)(AsyncUI);
In asyncContainer.js you can see the call to my simple UI component
return (
<AsyncUI />
);
But on calling the property of the redux store items in asyncUI.js an empty array, therefore the items.map fails
However, if I remove the code from asyncUI.js and place it in asyncContainer.js it works
This is the code that works in asyncContainer.js
class AsyncContainer extends Component {
componentDidMount() {
this.props.fetchData('http://5826ed963900d612000138bd.mockapi.io/items');
}
render() {
if (this.props.hasErrored) {
return <p>Sorry! There was an error loading the items</p>;
}
if (this.props.isLoading) {
return <p>Loading…</p>;
}
//THIS IS WHERE I HAD <Async />
return (
<ul>
{this.props.items.map((item) => (
<li key={item.id}>
{item.label}
</li>
))}
</ul>
);
}
}
AsyncContainer.propTypes = {
fetchData: PropTypes.func.isRequired,
items: PropTypes.array.isRequired,
hasErrored: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired
};
const mapStateToProps = (state) => {
return {
items: state.items,
hasErrored: state.itemsHasErrored,
isLoading: state.itemsIsLoading
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(itemsFetchData(url))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(AsyncContainer);
I think the problem is that the component is rendering before the items data is ready. This is normal react behavior. So how do I "hold off" the rendering. As you can see I'm trying to use a Container /Component style of architecture. I can always use the solution that works as mentioned above, but I'd like to stick with this Container /Component.
Am I going to have to delve deeper into Promises etc ?
Should I not use the functional way of writing for asyncUI.js ?
I'm a little confused.
Try:
const AsyncUI = ({items}) => {
/* ^ see ^ */
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item.label}
</li>
))}
</ul>
); }
This pulls the items value off the props you reacted in the mapStateToProps function, which is an object, not an array (hence no map function).
NOTE: This should fix your issue, but it is still technically trying to render the items before they are ready in 2 instances:
The first time the component renders. The initial state for itemsIsLoading is false, so the first render will fail all the safety checks. The default value for items is [] so it should just render <ul></ul> for a very brief moment until the itemsIsLoading(true) action is dispatched. You can set the initial state to true for stop this, or change the loading check to be
if (this.props.isLoading || this.props.items.length != 0) {
return <p>Loading…</p>;
}
An argument can be made for how necessary either of those solutions actually are.
After the fetch returns the order the actions is dispatched in will result in another brief render of <ul></ul> as the loading state is set to false before the items are set. See dgrijuela's answer for one way to fix this. Another way would be to not dispatch seperate actions and have the ITEMS_FETCH_DATA_SUCCESS and ITEMS_HAS_ERRORED actions also change the itemsIsLoading value back to false (multiple reducers can act on the same action type).
You call dispatch(itemsIsLoading(false)) before dispatch(itemsFetchDataSuccess(items))
Try like this:
// async.js
...
export function itemsFetchData(url) {
return (dispatch) => {
dispatch(itemsIsLoading(true));
fetch(url)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
})
.then((response) => response.json())
.then((items) => {
dispatch(itemsFetchDataSuccess(items));
dispatch(itemsIsLoading(false));
})
.catch(() => dispatch(itemsHasErrored(true)));
};
}
see Michael Peyper for a good answer
It turns out that the problem was with the functional style of coding of my asyncUI component. I converted it back to the 'standard' stateful component and bingo it worked.
asyncContainer.js
class AsyncContainer extends Component {
componentDidMount() {
this.props.fetchData('http://5826ed963900d612000138bd.mockapi.io/items');
}
render() {
if (this.props.hasErrored) {
return <p>Sorry! There was an error loading the items</p>;
}
if (this.props.isLoading) {
return <p>Loading…</p>;
}
return (
<AsyncUI />
)
}
}
asyncUI.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux'
class AsyncUI extends Component {
render() {
return (
<ul>
{this.props.items.map((item) => (
<li key={item.id}>
{item.label}
</li>
))}
</ul>
)
}
}
const mapStateToProps = (state) => {
return {
items: state.items,
};
};
export default connect(mapStateToProps)(AsyncUI);
Hope this helps anyone :-)

Reusing Reducer Logic does not toggle object using Redux and React'

I am reusing the same reducer logic for two different events. The idea is to toggle a class depending on which text you clicked on. Each event fires, but my object is not toggling. Any thoughts?
App:
import React from "react"
import { bindActionCreators } from 'redux'
import { connect } from "react-redux"
import * as toggleactionCreators from '../actions/toggleActions';
function mapStateToProps(state) {
return {
hiddenA: state.toggleA.hidden,
hiddenB: state.toggleB.hidden
}
}
function mapDispachToProps(dispatch) {
return bindActionCreators({...toggleactionCreators}, dispatch)
}
class Main extends React.Component {
toggleDiv() {
this.props.toggleDiv();
console.log(this.props)
}
render() {
const { hiddenA, hiddenB } = this.props;
return (
<div>
<div>
<h3 onClick={this.toggleDiv.bind(this)} className={ hiddenA ? null : "toggled"} >Good Day!</h3>
<h1 onClick={this.toggleDiv.bind(this)} className={ hiddenB ? null : "toggled"} >Hello There!</h1>
</div>
</div>
)
}
}
export default connect(mapStateToProps, mapDispachToProps)(Main);
Index Reducer:
import { combineReducers } from "redux"
import toggle from "./toggleReducer"
function createNamedWrapperReducer(reducerFunction, reducerName) {
return (state, action) => {
const {name} = action;
const isInitializationCall = state === undefined;
if(name !== reducerName && !isInitializationCall) return state;
return reducerFunction(state, action);
}
}
const thereducer = combineReducers({
toggleA : createNamedWrapperReducer(toggle, 'A'),
toggleB : createNamedWrapperReducer(toggle, 'B'),
});
export default thereducer;
toggleReducer:
const toggle = (state = { hidden: true}, action) => {
switch(action.type) {
case 'TOGGLE_DIV':
return Object.assign({}, ...state, {hidden: !state.hidden});
default:
return state;
}
};
export default toggle;
toggleAction:
export const toggleDiv = () => {
return {
type: 'TOGGLE_DIV',
}
}
This is how I would debug this.
Download Redux DevTools for your browser. This is the URL for chrome: https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd
Download React devtools for you browser. This is the URL for chrome: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
Look in Redux Devtools:
Is the action emitted from your action creator
Does the reducer update the state correctly?
If both the actions, and reducers looks correctly, check your React component:
Does the component receive the correct props? If yes, it's something with how the props are rendered. If no, it's something with how the store is connected to your component.
Hope this debugging tutorial is useful for you. If you have any follow up questions, please don't hesitate to ask :)

Resources