Как установить Div-оператор «Загрузка» Div внутри React Component с двумя операторами Return? - PullRequest
0 голосов
/ 01 октября 2019

API, который я использую, работает медленно. Мой компонент React использует FetchAPI и имеет два оператора возврата.

Я хочу включить условие троичного оператора, которое будет отображать «Загрузка ...», пока я жду данных , как это : https://codesandbox.io/s/api-fetch-using-usestate-useeffect-k024k

Как мне включить троичный "Загрузка" с двумя операторами возврата в мой код ниже? Примечание: я радикально сократил свой код, чтобы никто не сошел с ума, поэтому я включил только общую структуру. Не за что!

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
    };
  }

  componentDidMount() {
    fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({ data: data}))
  }

  render() {

    let theList = this.state.map((item, id) => {

      return (
        <Card>A bunch of API Stuff </Card>
      );

    })
    return (
      <div className="search-wrap">
        <Row>
          {theList}
        </Row>
      </div>
    )
  }
}

export default App;

Ответы [ 4 ]

0 голосов
/ 01 октября 2019

Вы можете сделать что-то вроде этого. Обратите внимание, что вы можете экспортировать непосредственно класс с самого начала. Также вы можете упростить состояние без явного конструктора. Чтобы узнать состояние выборки, вы должны добавить условие isLoading до и после выборки данных. Затем при рендеринге вы можете вернуть один отдельный узел, а внутри рендеринга - компоненты, которые вы хотите, основываясь на вашем статусе. С этим стилем кодирования вы можете даже показать, когда выборка возвращает пустой массив.

export default class App extends Component {
  state = {
    data: [],
    isLoading: false
  }
  componentDidMount() {
    this.setState({
      isLoading: true
    }, () => {
      fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({
        data,false
      }))
    })
  }
  render() {
    return (
      <div>
      {
        this.state.isLoading &&
        <span>
          Loading...
        </span>
      }
      {
        !this.state.isLoading &&
        (this.state.data.length > 0) &&
        <div className="search-wrap">
          <Row>
            {
              this.state.data.map((item, id) => {
                return (
                  <Card key={id}>
                    A bunch of API Stuff
                  </Card>
                );
               })
            }
          </Row>
        </div>
      }
      {
        !this.state.isLoading &&
        (this.state.data.length === 0) &&
        <span>
          There's no data to show
        </span>
      }
      </div>
    )
  }
}

Надеюсь, это поможет! Denny

0 голосов
/ 01 октября 2019

Мой компонент React использует FetchAPI и имеет два оператора возврата.

Нет, это не так. У него один:

render() {

  let theList = this.state.map((item, id) => {

    return (
      <Card>A bunch of API Stuff </Card>
    );

  })
  return (                               // <========== here
    <div className="search-wrap">
      <Row>
        {theList}
      </Row>
    </div>
  )
}

Другой - return в вашем map обратном вызове, который никак не влияет на ваш render метод.

Если вы хотите использовать условный оператор для отображения индикатора загрузки, вы сделаете это в вашем render возвращении:

render() {
  let { loading } = this.state; // *** Get the flag

  let theList = this.state.map((item, id) => {

    return (
      <Card>A bunch of API Stuff </Card>
    );

  })
  return (                          // *** Use it in the below
    <div className="search-wrap">
      <Row>
        {loading ? <p>Loading...</p> : theList}
      </Row>
    </div>
  )
}

Вы также можете избежать ненужного вызова map,но если вы знаете, что ваше состояние инициализируется пустым массивом, этот вызов безвреден. Но если вы хотите избавиться от этого:

render() {
  let { loading } = this.state; // *** Get the flag

  let theList = !loading && this.state.map((item, id) => {

    return (
      <Card>A bunch of API Stuff </Card>
    );

  })
  return (                          // *** Use it in the below
    <div className="search-wrap">
      <Row>
        {loading ? <p>Loading...</p> : theList}
      </Row>
    </div>
  )
}
0 голосов
/ 01 октября 2019

Если я правильно понимаю, ваш код должен выглядеть следующим образом:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      isLoading: false
    };
  }

  componentDidMount() {
    this.setState({ isLoading: true }); // mount the loading component when we will start the fecth
    fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({ data: data}))
      .then(() => this.setState({ isLoading: false })) // unmount Loading component when the fetch ends
  }

  render() {
    let theList = this.state.map((item, id) => {
      return (
        <Card>A bunch of API Stuff </Card>
      );
    })

    // Here we will return the Loading component as long as isLoading is true
    return (isLoading) ? <Loading /> : (
      <div className="search-wrap">
        <Row>
          {theList}
        </Row>
      </div>
    )
  }
}

export default App;

Поэтому в основном мы добавим логическую переменную (isLoading), которая будет обрабатывать состояние выборки, и добавим ее всостояние компонента. Когда выборка запущена, эта переменная будет true, в противном случае она будет false.

Так что тогда в операторе return мы можем использовать троичный оператор, основанный на значении этой новой переменной,Если это true, мы вернем загружающий компонент или простое div, говорящее Loading.... В противном случае мы вернем компонент App с загруженными данными.

Надеюсь, это поможет:)

0 голосов
/ 01 октября 2019

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

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      loading: true, // this one
    };
  }

  componentDidMount() {
    fetch('https.data.json')
      .then(response => response.json())
      .then(data => this.setState({ data: data, loading: false }))
  }

  render() {

    if (this.state.loading)
       return <div>Loading...</div>

    let theList = this.state.map((item, id) => {

      return (
        <Card>A bunch of API Stuff </Card>
      );

    })
    return (
      <div className="search-wrap">
        <Row>
          {theList}
        </Row>
      </div>
    )
  }
}

export default App;
...