Как решить проблему загрузки данных в React redux - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь выяснить, как я могу управлять / отображать этот компонент, когда данные все еще загружаются.

Я использую реагирующий редукс для этого случая.

любое предложение для решения этой проблемы ?

Хотя я обернул это ленивой загрузкой, но, похоже, это не так уж много работает в этом случае.

Любые предложения для этого.

// Действия. js

export const getContact= () => dispatch => {
    dispatch(setResumesLoading());
    axios
        .get('/api/contacts')
        .then(res => 
            dispatch({
                type: GET_CONTACTS,
                payload: res.data
            })
        ).catch (err => dispatch (returnErrors(err.response.data, err.response.status)));
};

// компонент. js

import React, {Component} from 'react';
import {Grid, Cell, List, ListItem, ListItemContent, Button} from 'react-mdl';
import { connect } from 'react-redux';
import { getContact, deleteContact} from '../../actions/resumeActions';
import PropTypes from 'prop-types';

class Contact extends Component{

    static propTypes = {
        getContact: PropTypes.func.isRequired,
        deleteContact: PropTypes.func.isRequired,
        resume: PropTypes.object.isRequired,
        isAuthenticated: PropTypes.bool,
        auth: PropTypes.object.isRequired
    }

    componentDidMount() {
        this.props.getContact();
    }

    onDeleteContactClick = (id) => {
        this.props.deleteContact(id);
    };

    render(){
        const { contacts } = this.props.resume;
        const { user } = this.props.auth;

        return(
            <div>
                {/* {loading ? <Loading /> : <ResultsComponent results={data} />} */}
                 {contacts.map(({ _id, contact_name, contact_phone, contact_email, contact_skype, contact_image }) => (
            <Grid key={_id} timeout={100} classNames="fade">

               { this.props.isAuthenticated && (user.is_admin === true) ? 
                            <Button className="remove-btn"
                            color="danger"
                            size="sm"
                            onClick= {this.onDeleteContactClick.bind(this, _id)}>
                                &times;
                            </Button> : null }
                    <Cell col={6}>
                        <div style={{textAlign: 'center'}}>
                            <h2> {contact_name} </h2>
                            <img src={contact_image}
                            alt="avatar"
                            style={{height: '40%', borderRadius: '50%', width: '50%'}}
                            img-rounded />
                        </div>

                    </Cell>
                    <Cell col={6} className="contact-right-col text-center">

                        <h2 >Contact Me</h2>
                        <hr  className="resume-left-contact-section-border" />

                        <List>
                          <ListItem>
                            <ListItemContent  className="contact-list-item">
                                <i className="fa fa-phone-square" aria-hidden="true"/>
                                {contact_phone}
                            </ListItemContent>
                          </ListItem>
                        </List>

                    </Cell>
            </Grid>
            ))} 
            </div>


        )
    }
}



const mapStateToProps = (state) => ({
    resume: state.resume,
    isAuthenticated : state.auth.isAuthenticated,
    auth: state.auth
});

export default connect(mapStateToProps, {getContact, deleteContact }) (Contact);

content is still loading...

Ответы [ 2 ]

3 голосов
/ 17 апреля 2020

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

import * as types from "./actionTypes";

export function beginApiCall() {
  return { type: types.BEGIN_API_CALL };
}

export function apiCallError() {
  return { type: types.API_CALL_ERROR };
}

Затем вы можете использовать эти действия, отправляя их в нужное время.

export const getWorkexperience = () => dispatch => {
    dispatch(beginApiCall());
    axios
        .get('/api/workexperiences')
        .then(res => 
            dispatch({
                type: GET_WORKEXPERIENCE,
                payload: res.data
            })
        ).catch (err => dispatch(apiCallError(error)););
};

Затем вы должны создать новый редуктор для этого действия , Написание редуктора для этого немного сложно. Вам необходимо хранить количество выполняемых вызовов API и увеличивать или уменьшать их в зависимости от их статуса. Для этого вы можете добавить _SUCCESS к существующему типу действия во всех создателях и редукторах действий.

import * as types from "../actions/actionTypes";
import initialState from "./initialState";

function actionTypeEndsInSuccess(type) {
  return type.substring(type.length - 8) === "_SUCCESS";
}

export default function apiCallStatusReducer(
  state = initialState.apiCallsInProgress,
  action
) {
  if (action.type == types.BEGIN_API_CALL) {
    return state + 1;
  } else if (
    action.type === types.API_CALL_ERROR ||
    actionTypeEndsInSuccess(action.type)
  ) {
    return state - 1;
  }

  return state;
}
  //initialState.js
    export default {
      state1: [],
      state2: [],
      apiCallsInProgress: 0
    };

Оказавшись внутри компонента, после выполнения запроса на выборку вы можете использовать состояние этого редуктора для рендеринга счетчика или чего-либо, что вам нужно, просто извлекая его из редуктора.

  const loading = useSelector((state) => state.apiCallsInProgress > 0);

или вы можете получить к нему доступ через mapStateToProps, как это, которое, как я вижу, вы использовали для получения реквизита в вашем компоненте.

const mapStateToProps = (state) => ({
    resume: state.resume,
    isAuthenticated : state.auth.isAuthenticated,
    auth: state.auth,
    loading: state.apiCallsInProgress > 0
});

И вы можете вернуть содержимое функции следующим образом.

 {loading ? (
       Loading...
      ) : (
        <div>My component</div>
)}
0 голосов
/ 17 апреля 2020

Одним из распространенных способов представления компонента, особенно если это контейнер, является реализация индикатора активности загрузки, который исчезнет, ​​если у вас появятся данные для отображения. Просто убедитесь, что loading логическое значение реализовано в вашем локальном штате, и как только вы подтвердите наличие данных, измените loading на false.

async componentWillMount() {
  await getWorkexperience();
  this.setState({
     loading: false,
  });
}

...

render() {
  const { data, loading } = this.state;

  return (
    <div>
      {/*
        Check the status of the 'loading' variable. If true, then display
        the loading spinner. Otherwise, display the data.
      */}
      {loading ? <LoadingSpinner /> : <ResultsComponent results={data} />}
    </div>
  );

}

Это то, что вы искали?

Среди готовых решений есть пакеты, которые можно использовать сразу:

...