admin管理员组

文章数量:1401633

I have the following code:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Autoplete from "@material-ui/lab/Autoplete";
import axios from "axios";

var config = {
  headers: {
    Accept: "application/json; odata=verbose",
    Authorization: "Bearer " + access_token,
  },
};

class Searchbar extends React.Component {
   async ponentWillMount() {
    await axios.get(contracts, config).then((res) => {
      this.setState({ allContracts: res.data });
    });
  }
  render() {

    return (
      <div className="searchbar_wrapper">
        <Autoplete
          freeSolo
          id="contract-search-bar"
          disableClearable
          options={contracts.map((option) => option.name)}
          onChange={(event, value) => {
          let selectedContractID =(value)
          }}
          renderInput={(params) => (
            <TextField
              {...params}
              label="Search"
              margin="normal"
              variant="outlined"
              InputProps={{ ...params.InputProps, type: "search" }}
            />
          )}
        />
      </div>
    );
  }
}
export default Searchbar;

I am using ponent will mount as I want this function to first make a call before rendering my ponent... the axios call will get a result like below:

    results = [
      { name: "aaa" },
      { name: "bb" },
      { name: "cccc" },
    ];

The result would be over 500 entries..

The problem I have is when the ponent is rendering it keeps saying:

Cannot read property 'allContracts' of null

And the reason for this is because the axios function has not finished getting its results...

Please let me know how I can delay rendering and wait for axios to first get results and then continue

I have the following code:

import React from "react";
import TextField from "@material-ui/core/TextField";
import Autoplete from "@material-ui/lab/Autoplete";
import axios from "axios";

var config = {
  headers: {
    Accept: "application/json; odata=verbose",
    Authorization: "Bearer " + access_token,
  },
};

class Searchbar extends React.Component {
   async ponentWillMount() {
    await axios.get(contracts, config).then((res) => {
      this.setState({ allContracts: res.data });
    });
  }
  render() {

    return (
      <div className="searchbar_wrapper">
        <Autoplete
          freeSolo
          id="contract-search-bar"
          disableClearable
          options={contracts.map((option) => option.name)}
          onChange={(event, value) => {
          let selectedContractID =(value)
          }}
          renderInput={(params) => (
            <TextField
              {...params}
              label="Search"
              margin="normal"
              variant="outlined"
              InputProps={{ ...params.InputProps, type: "search" }}
            />
          )}
        />
      </div>
    );
  }
}
export default Searchbar;

I am using ponent will mount as I want this function to first make a call before rendering my ponent... the axios call will get a result like below:

    results = [
      { name: "aaa" },
      { name: "bb" },
      { name: "cccc" },
    ];

The result would be over 500 entries..

The problem I have is when the ponent is rendering it keeps saying:

Cannot read property 'allContracts' of null

And the reason for this is because the axios function has not finished getting its results...

Please let me know how I can delay rendering and wait for axios to first get results and then continue

Share Improve this question edited Jun 11, 2020 at 15:03 Gryu 2,1892 gold badges19 silver badges30 bronze badges asked Jun 11, 2020 at 13:41 HUS THUS T 331 silver badge3 bronze badges 3
  • you have 2 options: React.Suspense or ponentDidMount. In both cases you need to define default status first: state: {allContracts: [];} – demkovych Commented Jun 11, 2020 at 13:43
  • ponentDidMount happens after.. this still does not resolve the issue as my axios results need to loads before anything – HUS T Commented Jun 11, 2020 at 13:44
  • You must use the ponentDidMount and a loading state for a good practice. Take a look at the React lifecycle, it helps a lot i2.wp./programmingwithmosh./wp-content/uploads/2018/10/… – Pedro Mutter Commented Jun 11, 2020 at 13:56
Add a ment  | 

4 Answers 4

Reset to default 3

This will help. No need for ComponentWillMount. Also there is a need for error-handling.

import React, { Component } from "react";
import axios from "axios";

class Test extends Component {
  state = {
    allContracts: null,
    error: false,
    loading: false,
  };

  async getAllContracts() {
    setLoading(true);
    try {
      const response = await axios.get(contracts, config);
      this.setState({ allContracts: response.data });
    } catch (error) {
      this.setState({ error: true });
    } finally {
      setLoading(false);
    }
  }

  ponentDidMount() {
    this.getAllContracts();
  }

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

    if (loading) {
      return <div className="spinner"></div>; // add a spinner or something until the posts are loaded
    }

    if (error) {
      return <div className="error">Something went wrong</div>;
    }

    return allContracts.map((el, index) => {
      return <div key={index}>{...}</div>; // whatever you want to render
    });
  }
}

export default Test;

You can basically hold a "loading" state, and while the loading is true, render a spinner or something that the ponent shows.

You can do it like @pirhan mentioned:

    constructor() {
        this.state = {
            isLoaded: false
        }
    }

    async ponentDidMount() {
        const res = await axios.get(contracts, config);
        this.setState({ allContracts: res.data, isLoaded: true });
    }

    render() {
        if (!this.state.isLoaded) {
            return null /* or a loader/spinner */
        }

        return "I'm loaded ok."
    }

Manage a loading state as well as define your state like this:

import React from "react";
    import TextField from "@material-ui/core/TextField";
    import Autoplete from "@material-ui/lab/Autoplete";
    import axios from "axios";

    var config = {
      headers: {
        Accept: "application/json; odata=verbose",
        Authorization: "Bearer " + access_token,
      },
    };

    class Searchbar extends React.Component {

       state = {   //define state here
          allContracts: []
        }
       async ponentDidMount() {
        await axios.get(contracts, config).then((res) => {
          this.setState({ allContracts: res.data });
        });
      }
      render() {

        return (
          <div className="searchbar_wrapper">
          {   allContracts.length > 0 ?  //wait for data - manage loading state
            <Autoplete
              freeSolo
              id="contract-search-bar"
              disableClearable
              options={allContracts.map((option) => option.name)}
              onChange={(event, value) => {
              let selectedContractID =(value)
              }}
              renderInput={(params) => (
                <TextField
                  {...params}
                  label="Search"
                  margin="normal"
                  variant="outlined"
                  InputProps={{ ...params.InputProps, type: "search" }}
                />
              )}
            />
          : <h1>Loading.. </h1>
          </div>
        );
      }
    }
    export default Searchbar;

本文标签: javascriptHow can I make an axios get request wait before rendering my react componentStack Overflow