反应-在渲染之前加载数据

时间:2019-10-02 06:05:00

标签: javascript reactjs redux react-redux

我是新来的反应者,我有一个最佳实践的问题,认为我会犯错。 一旦API返回响应,我将调用API来检索信息并修改状态下的数组。在“渲染器”中,我必须从该数组中检索信息(完成时),或者因为初始化渲染器时该数组为空,它会向我发送错误。

export default async function addUserLogs(account, service, terminal,isSaved,isSentToGateway,amount ) {
  const obj = {};

  if(account) obj.amountName = account;
  if(service) obj.serviceID = service;
  if(terminal) obj.terminalID = terminal;
  if(isSaved !== null) obj.isSaved = isSaved;
  if(isSentToGateway !== null) obj.isSentToGateway = isSentToGateway;
  if(amount) obj.amount = amount;

  const db = await InitDb();
  const tx = db.transaction('userLogs', 'readwrite');
  const store = tx.objectStore('userLogs');
  const index = await store.put(obj);
  let params = {};
  if (window.localStorage.getItem('params') !== null) {
    params = JSON.parse(window.localStorage.getItem('params'));
  }
  window.localStorage.setItem(
    'params',
    JSON.stringify({ ...params, userLogIndex: index })
  );
} ```

错误表明:

  

TypeError:_items $ activeInde未定义

如何解决与数据加载相关的错误? (尝试保留destrying elements方法)

非常感谢 艾略特

4 个答案:

答案 0 :(得分:1)

因为您从服务器获取的API是异步。第一次渲染Component时,您在 axios setState 的数据仍未更新,只是在第二次渲染Component时更新。

因此,您必须像这样检查render Component中的状态,以确保如果activeIndex is defined然后用items[activeIndex]声明变量:

activeIndex && const {
      first_name: firstName,
      last_name: lastName,
      phone,
      email,
      address,
} = items[activeIndex]

答案 1 :(得分:0)

在第一次调用componentDidMount函数之后,调用

render。因此,当第一次调用render函数时,尚未发出任何HTTP请求。

要解决此问题,可以在render函数内部检查是否定义了activeIndex。如果未定义,则可以显示一些加载微调器或所需的任何内容。

render() {
    if (!this.state.activeIndex) {
        // show loading spinner
    } else {
        // do your work
    }
}

答案 2 :(得分:0)

只需更改组件,就像这样:

  constructor(props) {
    super(props)
    this.state = {
      activeIndex: 0,
      items: [],
      isFetching: false
    }
  }

  componentDidMount() {
    // staring your fetching
    this.setState({isFetching: true});
    axios
      .get(`API_ADDRESS`, {
        headers: {
          Authorization: `Token XXX`,
        },
      })
      .then(function(response) {
        // finish fetching when your response is ready :)
        this.setState({
          items: response.results,
          isFetching: false
        });
      })
      .catch(error => {
        // finish fetchnig
        this.setState({isFetching: false})
        notification.warning({
          message: error.code,
          description: error.message,
        })
      })
  }

  changeDialog = (e, index) => {
    e.preventDefault()
    this.setState({
      activeIndex: index,
    })
  }

  render() {

    // if your component is while fetching shows a loading to the user
    if(this.state.isFetching) return <div>Loading...</div>;
    // if there is no results shows a msg to the user
    if(this.state.items.length === 0) return <div>there is not items!!!</div>

    const { activeIndex, items } = this.state
    const {
      first_name: firstName,
      last_name: lastName,
      phone,
      email,
      address,
    } = items[activeIndex]

答案 3 :(得分:0)

两个问题:

  • 当心axios返回的this中的Promise。您使用function(){},因此内部的this不是组件的实例。将其更改为箭头功能。
  • 添加防护,以使undefined指向不存在的activeIndex元素时不会破坏item(在axios提取数据之前的初始加载中发生) 。

修复:

// ... (code not shown remains unmodified)
componentDidMount() {
  axios
    .get(`API_ADDRESS`, {
      headers: {
        Authorization: `Token XXX`,
      },
    })
    .then(response => {                                             // changed this line
      this.setState({
        items: response.results,
      })
    })
// ... (code not shown remains unmodified)

render() {
  const { activeIndex, items } = this.state
  if (!items[activeIndex]) {                                        // added this line
    return <div>Hold tight while items are being fetched...</div>;  // added this line
  }                                                                 // added this line
  const {
    first_name: firstName,
// ... (code not shown remains unmodified)