0

EDIT:

Here is a working jsComplete (use chrome) where I am assigning the JSON to the state instead making the api call. I am trying to do the same thing with the api call though.

How do I assign the value to the state property locoData before the render() method runs?

locoData never gets assigned, and the console.log(resp.data); executes after the render method. I am new to react, and just catching up with the newer features in JavaScript such as promises, and this is really confusing me. I am executing this code in jsComplete

If I assign the JSON to the state instead of trying to use the axios.get method, it works fine. JSON response is at the bottom.

I removed my bing map key.

  const LocationData = (props) => (
    <div>
      {props.location => <Location key={location.traceId} {...location}/>}
    </div>
)

class Location extends React.Component {    
    state = { locoData: {} },   
    const a = axios.get("https://dev.virtualearth.net/REST/v1/Locations?CountryRegion=US&adminDistrict=WA&locality=Somewhere&postalCode=98001&addressLine=100%20Main%20St.&key=bingMapKey").then(resp => { 
      console.log(resp.data);
      this.setState({ locoData: resp.data });  
    });

  render() {     
    resources = this.state.locoData.resourceSets[0].resources.map(function(resource){      
      return <div className="resource" key={resource.name} {...resource}></div>;
    });
    return (
        <div>
          <img src={location.brandLogoUri} />
        <div>
          <div>{resources.name}</div>
          <div>{resources[0].props.point.coordinates[0]} {resources[0].props.point.coordinates[1]}</div>
        </div>
        </div>
    );
  }
}

class App extends React.Component {
  state = {
    location: [],
  };
  displayLocation = (locationData) => {
    this.setState(prevState => ({
        location: [...prevState.location, locationData],
    }));
  };
    render() {
    return (
        <div>
          <div>{this.props.title}</div>
        <Location LocationData={this.state.location} />
        </div>
    );
  } 
}

ReactDOM.render(
    <App title="Simple Weather App" />,
  mountNode,
);

{"authenticationResultCode":"ValidCredentials","brandLogoUri":"http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png","copyright":"Copyright © 2019 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.","resourceSets":[{"estimatedTotal":1,"resources":[{"__type":"Location:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1","bbox":[47.275809008582883,-122.25881456692279,47.283534443724236,-122.24363249293789],"name":"100 Main St, Algona, WA 98001","point":{"type":"Point","coordinates":[47.279671726153559,-122.25122352993034]},"address":{"addressLine":"100 Main St","adminDistrict":"WA","adminDistrict2":"King County","countryRegion":"United States","formattedAddress":"100 Main St, Algona, WA 98001","locality":"Algona","postalCode":"98001"},"confidence":"High","entityType":"Address","geocodePoints":[{"type":"Point","coordinates":[47.279671726153559,-122.25122352993034],"calculationMethod":"InterpolationOffset","usageTypes":["Display"]},{"type":"Point","coordinates":[47.279653371643015,-122.25128403728938],"calculationMethod":"Interpolation","usageTypes":["Route"]}],"matchCodes":["Good"]}]}],"statusCode":200,"statusDescription":"OK","traceId":"591320e018b0476cbbe71f338ecab555|BN1EAE8F4E|7.7.0.0|Ref A: 3983F574345D41A782020BC15BA6BF08 Ref B: BN3EDGE0210 Ref C: 2019-05-04T04:30:29Z"}
Popo
  • 2,402
  • 5
  • 33
  • 55

2 Answers2

1

I don't know if it's the correct answer to your problem. React has a render cycle that you can find here:

https://reactjs.org/docs/react-component.html?utm_source=caibaojian.com
Or
https://reactjs.org/docs/state-and-lifecycle.html

You can do that in two ways the first one is using the function

 componentWillMount(){
    //Here you can set state normally
    }

that is ran before the component Is mount. The second solution is using the new feature of react hooks using that, in this case, is the same as componentWillMount

useEffect(() => {
  return () => {
    //here you can set your state
  }
}, [])

PS: Just use hooks, the old react cycle is deprecated

Gianmarco
  • 792
  • 2
  • 14
  • 38
  • I have tried using `componentWillMount()` with no success. I will read up on your links. – Popo May 04 '19 at 05:23
  • what is resp.data? – Gianmarco May 04 '19 at 05:28
  • 1
    https://stackoverflow.com/questions/49206280/componentwillmount-is-deprecated-and-will-be-removed-in-the-next-major-version-0 – Junius L May 04 '19 at 05:31
  • @Gianmarco that's a response – Junius L May 04 '19 at 05:31
  • oh, so use just hooks – Gianmarco May 04 '19 at 05:31
  • @Gianmarco the JSON from the resp.data is in the bottom of the question, I also updated the question with jsComplete.com where I use the JSON instead of the api call, which works, but not what I need. – Popo May 04 '19 at 05:33
  • you don't need hooks here. – Junius L May 04 '19 at 05:33
  • @JuniusL. thanks for the link about the deprecated method. – Popo May 04 '19 at 05:34
  • and also it's hard for us suggest a solution if we don't know what's being returned from the api. – Junius L May 04 '19 at 05:36
  • @JuniusL. the JSON from the api is at the bottom of the question. Here is an example that just uses the JSON, instead of the api call https://jscomplete.com/playground/s267152 – Popo May 04 '19 at 05:44
  • 1
    @Gianmarco Thanks for the input, but conditional rendering was the solution. I am still going to read up on hooks though as it looks like something I will need to know and understand. It was mentioned in the course I was taking on pluralsight. – Popo May 04 '19 at 15:31
1

You need to use conditional rendering, have a variable set to true like state = { isLoading: true } once you receive data from the api, you set it to false.

conditional rendering tutorial

class Location extends React.Component {
  state = { locoData: {}, isLoading: true, errorMessage: "" };

  getDataFromApi = () => {
    const t_his = this;
    const a = axios
      .get(
        "https://dev.virtualearth.net/REST/v1/Locations?CountryRegion=US&adminDistrict=WA&locality=Somewhere&postalCode=98001&addressLine=100%20Main%20St.&key=bingMapKey"
      )
      .then(resp => {
        console.log(resp.data);
        t_his.setState({ locoData: resp.data, isLoading: false });
      })
      .catch(function(error) {
        t_his.setState({
          errorMessage: "Error occured with status: " + error.response.status,
          isLoading: false
        });
      });
  };

  componentDidMount = () => {
    this.getDataFromApi();
  };

  render() {

    const resourcesData =
      (this.state.locoData &&
        this.state.locoData.resourceSets &&
        this.state.locoData.resourceSets[0].resources) ||
      [];

    const resources = resourcesData.map(function(resource) {
      return <div className="resource" key={resource.name} {...resource} />;
    });

    const name = (resources && resources[0] && resources[0].props.name) || "";
    const coordinates =
      (resources && resources[0] && resources[0].props.point.coordinates[0]) ||
      "";
    const coordinates1 =
      (resources && resources[0] && resources[0].props.point.coordinates[1]) ||
      "";

    return (
      <div>
        {this.state.isLoading ? (
          <Loader type="Puff" color="#00BFFF" height="100" width="100" />
        ) : (
          <div>
            {!!this.state.errorMessage ? (
              <h2>{this.state.errorMessage}</h2>
            ) : (
              <div>
                <img src={this.state.locoData.brandLogoUri} />
                <div>
                  <div>{name}</div>
                  <div>
                    {coordinates} {coordinates1}
                  </div>
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    );
  }
}

Demo

Junius L
  • 15,881
  • 6
  • 52
  • 96
  • 1
    Awesome, I created a Loader class for the condition, and this works perfectly, and I see what you are doing here with the conditional state property, and using it in the render() return. Now on to the next part to use the NOAA api to pass the coordinates in and get the current weather. Then I am going to add inputs for the user to enter an address. I thought this would be a good challenge to practice what I am learning. Thanks for the assist! – Popo May 04 '19 at 15:29