在获取数据之前禁止渲染

时间:2019-08-27 11:59:17

标签: javascript reactjs redux react-redux

我试图阻止组件加载,直到它从API(如Instagram)中获取数据为止。我只希望旧组件一直显示直到新组件准备就绪。请问我该怎么做Reactjs

import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import Main from "../main";
import { connect } from "react-redux";
import {
  getBooks,
  getMoreBooks,
  addToLibrary,
  search
} from "../../actions/books";
import { showLoading, hideLoading } from "react-redux-loading-bar";
import BottomScrollListener from "react-bottom-scroll-listener";
class Books extends Component {
  constructor(props) {
    super(props);
    this.props.showLoading();
    this.state = { isFetching: false, search: "", shouldScroller: false };
  }


  // componentWillMount() {
  //   this.props.showLoading();
  // }

  async componentDidMount() {
    if (!this.props.books.length > 0) {
      await this.props.getBooks();
    }
    // this.props.hideLoading();
  }
  componentDidUpdate(prevProps) {
    if (prevProps.book_next_url !== this.props.book_next_url) {
      setTimeout(
        this.setState({
          isFetching: false
        }),
        800
      );
    }
    if (prevProps.books != this.props.books) {
      this.props.hideLoading();
    }
  }

  componentWillUnmount() {
    // this.setState({ shouldScroller: false });
    // this.props.showLoading();
  }

  render() {
    if (this.props.booksIsLoading) {
      return <Main />;
    }
    return (
      <div>
        <BottomScrollListener
          onBottom={this.handleScroller}
          debounce={600}
          offset={30}
        />
        <Main />
    );
  }
}

我已经在上面展示了我想要渲染的整个组件的细节。

1 个答案:

答案 0 :(得分:0)

我认为您希望在加载数据时从旧组件切换到数据组件。下面的代码显示了如何使用Switch组件。

import React, { useEffect, useReducer } from 'react';

const Data = props => (
  <div>
    here is the data: {JSON.stringify(props, undefined, 2)}
  </div>
);

const OldComponent = props => (
  <div>
    this is the old component loading is{' '}
    {props.loading ? 'true' : 'false'}
    <button
      onClick={props.loadData}
      disabled={props.loading}
    >
      load data
    </button>
  </div>
);
//general Switch component function that will render
//one or other based on the switchFn returning true or false
const Switch = (one, other, switchFn) => props =>
  switchFn(props) ? one(props) : other(props);

const reducer = (state, action) => {
  switch (action.type) {
    case 'load':
      return { ...state, loading: true };
    case 'received':
      return {
        ...state,
        loading: false,
        data: action.data,
        showOther: true,
      };
    default:
      return state;
  }
};
const initialState = { loading: false };

const DataSwitch = Switch(
  OldComponent,
  Data,
  //show Oldcomponent if props.showOther is false
  props => !props.showOther
);

export default () => {
  //pretend redux
  const [state, dispatch] = useReducer(
    reducer,
    initialState
  );
  //loadData action
  const loadData = () => dispatch({ type: 'load' });
  //pretend middleware to get data, will be executed if
  // loading changes
  const { loading } = state;
  useEffect(() => {
    if (loading === true) {
      new Promise(resolve =>
        setTimeout(() => resolve([1, 2, 3]), 1000)
      ).then(data => dispatch({ type: 'received', data }));
    }
  }, [loading]);

  return DataSwitch({ ...state, loadData });
};