Реагирует на получение статуса Invalid при использовании asyn c action creator с redux-thunk - PullRequest
0 голосов
/ 22 марта 2020

В моем компоненте приложения у меня есть список постов, который содержит идентификатор пользователя, я хочу отобразить имя пользователя и данные этого идентификатора пользователя, вот jsx моего компонента приложения:

Компонент приложения JSX:

render() {
    const posts = [...someListOfPosts];
    return posts.map((post) => {
        return (
            <div className="item" key={post.id}>
                <div className="content">
                    <User userId={post.userId} />
                </div>
            </div>
        );
    });
}

Пользовательский компонент

import React from 'react';
import { connect } from 'react-redux';
import { fetchUser } from '../actions';

class UserHeader extends React.Component {

    componentDidMount() {
        this.props.fetchUser(this.props.userId); // getting correct userId
    }

    render() {
        const { user } = this.props;
        // Not displaying correct user i.e. showing the last resolved user for each post
        return (
            <div>
                {user && <div className="header">{user.name}</div>}
            </div>
        );
    }
}

const mapStateToProps = (state, props) => {
    return {
        user: state.user
    };
}

export default connect(mapStateToProps, { fetchUser })(UserHeader);

Я получаю правильные реквизиты для userId, но для каждого сообщения отображается последний разрешенный пользователь из API , Он должен быть релевантным пользователем для каждого сообщения.

Reducer and Action Creator

// action

export const fetchUser = (id) => {
    return async (dispatch) => {
        const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`);
        dispatch({
            type: 'FETCH_USER',
            payload: (response.status === 200 && response.data) ? response.data : null; // it returns single user not array of user
        });
    }
}

// reducer

export default (state = null, action) => {
    switch (action.type) {
        case 'FETCH_USER':
            return action.payload; // i know it can be fixed by defaulting state to empty array and returning like so [...state, action.payload] but why should i return complete state why not just a single user object here?
        default:
            return state;
    }
}

Создатель действия fetchUser возвращает одну полезную нагрузку пользователя, а не массива, тогда почему требуется вернуть состояние, например [...state, action.payload], почему это невозможно сделать, только action.payload? Я пробовал это, возвращая только action.payload, но в моем пользовательском компоненте он отображает последнего разрешенного пользователя из API каждый раз для каждого сообщения. Я запутался в этом.

1 Ответ

0 голосов
/ 22 марта 2020

Вы подписываетесь на магазин, используя mapStateToProps, который пересматривается всякий раз, когда происходит изменение в магазине. Поскольку вы пытаетесь выполнить рендеринг через реквизиты в компоненте «Пользователь», приложение сохраняет последнее значение «Пользователь» и повторно отображает все старые компоненты «Пользователь». Если вы хотите игнорировать обновления реквизита, сделайте результат локальным для компонента.

Вы можете попробовать это:

import React from 'react';
import { connect } from 'react-redux';
import { fetchUser } from '../actions';

class UserHeader extends React.Component {
constructor(props){
super(props);
this.state={
userDetails:{}
}
}

    componentDidMount() {
fetch(https://jsonplaceholder.typicode.com/users/${this.props.userId})
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            userDetails: result.data
          });
        },
        // Note: it's important to handle errors here
        // instead of a catch() block so that we don't swallow
        // exceptions from actual bugs in components.
        (error) => {
          this.setState({
            isLoaded: false
          });
        }
      )

    }

    render() {
        return (
            <div>
                {this.state.userDetails && <div className="header">{this.state.userDetails.name}</div>}
            </div>
        );
    }
}

const mapStateToProps = (state, props) => {
    return {

    };
}

export default connect(mapStateToProps, { fetchUser })(UserHeader);
...