Flashcap
Flashcap

Reputation: 141

Can't check if a value in props is defined

So I have been trying to solve this problem in a couple of ways but none of them really worked. I use Redux with React so I want to use the date from the store in my react component.

The problem is, the data is not the on the first render, so the variable I am trying to access is undefined.

const { errors } = this.props;
let errorList = null;
if(errors){
    errorList = Object.keys(this.props.error).map(function(key) {
    return <li className = "list-group-item list-group-item-danger" key = {errors[key]}>   {errors[key]}</li>;
    });
}

I tried to make a const out of the props value I want to use, but that doesn't help since that becomes undefined as well.

I tried writing a simple if statement to check if the value is undefined, but still no luck:

if(this.props.errors && typeof this.props.errors !== 'undefined'){ ... }

In my reducer, I have an initial state, so I am not sure why it becomes undefined despite that. Maybe I am just doing the initialization wrong.. Here is my reducer:

import { SET_ERRORS } from '../actions/creators/types';

const initialState = {}

export default function reducerError(state = initialState, action){
    switch(action.type){
        case SET_ERRORS:
            return action.payload;
        default:
            return state;
    }
}

I searched for a solution, some of the suggested using componentWillReceiveProps, but that is deprecated, and if there is a better solution, I wouldn't want to use it.

How can I make sure the code only runs if the props arrived? I am using this one in a form to get back error messages, but I have different ones too, and they don't really work either. Some of them does, but I am doing the exact same thing here, and this just doesn't.

Upvotes: 1

Views: 361

Answers (2)

Tony Drummond
Tony Drummond

Reputation: 375

This is how I use Redux to extract state from store and use within a component. This likely won't solve all of your problems, but will show a concise example.

import React, {useEffect} from 'react'
import {useDispatch, useSelector} from "react-redux";
import getStuffFromDB from "../actions/getStuff"

const Example = () => {

    const dispatch = useDispatch();

    const stuffFromState = useSelector(state => state.stuff); // stuff is part of our state in the store
    const {error, loading, stuff} = stuffFromState; // destructure state

    useEffect(()=>{
        dispatch(getStuffFromDB()) // get stuff from the database
    }, [dispatch])

    return (
        <>
            {/* Show loader if loading */}
            {loading && <Loader />}
            {/* Show error message if exists */}
            {error && <Message severity="error">{error}</Message>}
            <div>
                <p>{stuff}</p>
            </div>
        </>
    )
}

export default Example

Example reducer (note I am using thunk middleware):

export const getStuffReducer = (
    state = { stuff: [] },
    action
) => {
    switch (action.type) {
        case STUFF_FROM_DATABASE_REQUEST:
            return { loading: true };
        case STUFF_FROM_DATABASE_SUCCESS:
            return {
                loading: false,
                stuff: action.payload,

            };
        case STUFF_FROM_DATABASE_FAIL:
            return { loading: false, error: action.payload };
        default:
            return state;
    }
};

Example action:

export const getStuffFromDB = () => async dispatch => {
    try {
        dispatch({ type: STUFF_FROM_DATABASE_REQUEST });
        const { data } = await axios.get("/api/stuff");
        dispatch({ type: STUFF_FROM_DATABASE_SUCCESS, payload: data });
    } catch (error) {
        dispatch({
            type: STUFF_FROM_DATABASE_FAIL,
            payload:
                error.response && error.response.data.message
                    ? error.response.data.message
                    : error.message,
        });
    }
};

Store setup:

import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";


const reducer = combineReducers({
    stuff: getStuffReducer,
});

// Set initial state
const initialState = {};

// Configure thunk middleware
const middleware = [thunk];

// Configure store
const store = createStore(
    reducer,
    initialState,
    composeWithDevTools(applyMiddleware(...middleware))
);

export default store;

Upvotes: 0

Flashcap
Flashcap

Reputation: 141

I had a typo at

errorList = Object.keys(this.props.error).map(function(key) {

That this.props.error should have been 'errors'.

Upvotes: 1

Related Questions