react props incorrect value

时间:2017-12-18 04:53:28

标签: javascript reactjs redux

I am handling a 404 error by changing the redux state in a React app, so if the there's an error, I update the state.error to 404 and I render a component depending on that state. This the display() function inside my React container.

display() {
        const { weather: { weathers } } = this.props;
        const error = this.props.weather.error;
        console.log('props ', this.props);
        console.log('props weather', this.props.weather, 'w err', this.props.weather.error);
        console.log('error ', error);

        if (error !== 0) {
            return <ErrorMssg error={error} />;
        }

        if (weathers.length === 1) {
            return  <div>hai</div>;
        }

        return <Chart data={weathers}/>;
    }

I console log this.props and the redux state in the mapStateToProps function, and I can see the state updates successfully if there's a 404 catch. I can even see that if I console log this.props in the chrome console, and I expand it I can see the error value as I would expect (although the value before the object expansion is not the one that shows after the expansion, see image), but if I console log this.props.weather.error it shows me an unexpected value.

Here is the chrome console log:

enter image description here

here's the code of the reducer

export default (state: I.StoreState = defaultState, action: T.AWeather): I.StoreState => {
    const { type, payload } = action;
    switch (type) {
        case FETCH_WEATHER:
            const _data = 'data';
            const data = payload[_data];
            const { name, country } = data.city;

            const weathers: I.Weather[] = [];
            for (let i = 0; i < data.list.length; i = i + 3) {
                let item = data.list[i];
                let { dt_txt } = item;
                let schedule = dt_txt ? dt_txt.split(' ') : '';
                let { humidity, pressure, temp } = item.main;

                weathers.push({
                    date: schedule[0],
                    time: schedule[1],
                    humidity,
                    pressure,
                    temp
                });
            }

            return {
                city: { name, country },
                weathers,
                error: 0
            };

        case ERROR_NOT_FOUND:
            defaultState.error = 404;
            return defaultState;

        default:
            return state;
    }
};

And here;s the code of the action

export const fetchWeather = (searchValues: I.Search): T.AWeather | object => {
    const { city, country } = searchValues;

    const url: string = `${ROOT_URL}&q=${city},${country}`;

    const response: T.AWeather | object = axios.get(url)
        .then( res => ({
            type: FETCH_WEATHER,
            payload: res
        }))
        .catch( error => ({
            type: ERROR_NOT_FOUND,
            payload: error.response.status
        }));

    return response;
};

EDIT

Note: I am using redux-form that updates the redux state when I click a form input, so after I submit and the error still shows as 0, but when I click the form it does logs and renders as expected.

Also, when I expand the console log in Chrome it shows it updated the state (even if it's after the log, showing Chrome's object's revaluation like Dan O explained).. shouldn't the container re-render when the state is changed??

2 个答案:

答案 0 :(得分:0)

when you console.log an object to the Chrome console, you see a few fields in that object and also a triangle icon which you can click to expand the object and view its complete contents. When you click that icon, Chrome re-evaluates the contents of the object. Those contents might be different now than what they were when you logged to console, e.g. if a state object is mutated.

See here for more information: Getting chrome console to show object values as they were.

So that is why you have a mismatch between this.state and console.log.

But also, according to your image you are rendering your component before your axios request returns. error is set to 0 (maybe in defaultState?) so console.log gives you 0, then axios returns 404 some time in the future. You'll need to make another state update or trigger a re-render some other way if you want to see those changes rendered in your component.

答案 1 :(得分:0)

好的,我发现了发生了什么..问题是我以前做过的减速机的返回:

case ERROR_NOT_FOUND:
            defaultState.error = 404;
            return defaultState;

,其中

const defaultState: I.StoreState = {
    city: {name: '', country: ''},
    weather: [{
        date: '',
        time: 'string',
        humidity: 0,
        pressure: 0,
        temp: 0
    }],
    error: 0
};

我认为既然我没有改变状态,只是返回一个新对象它会起作用,但事实并非如此,你必须像这样返回:

case ERROR_NOT_FOUND:
            return {
                city: defaultState.city,
                weather: defaultState.weather,
                error: 404
            };