如何在执行render方法之前为带有状态的状态赋值

时间:2019-05-04 04:35:29

标签: javascript reactjs axios es6-promise es6-class

编辑:

Here is a working jsComplete(使用chrome),在这里我将JSON分配给状态而不是进行api调用。我正在尝试通过api调用执行相同的操作。

在运行locoData方法之前,如何将值分配给状态属性render()

locoData从未分配,并且console.log(resp.data);在render方法之后执行。我是新来的反应者,只是赶上JavaScript中的新功能(如promises),这确实使我感到困惑。我正在jsComplete

中执行此代码

如果我将JSON分配给该状态而不是尝试使用axios.get方法,则它可以正常工作。 JSON响应位于底部。

我删除了必应地图密钥。

  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"}

2 个答案:

答案 0 :(得分:1)

我不知道这是否是您问题的正确答案。 React有一个渲染周期,您可以在这里找到:

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

https://reactjs.org/docs/state-and-lifecycle.html

您可以通过两种方式做到这一点,第一种是使用功能

 componentWillMount(){
    //Here you can set state normally
    }
在安装组件之前运行的

。 第二种解决方案是使用react挂钩的新功能,在这种情况下,它与componentWillMount

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

PS: 仅使用钩子,不赞成使用旧的反应周期

答案 1 :(得分:1)

您需要使用条件渲染,将变量设置为true就像state = { isLoading: true }一样,一旦您从api接收到数据,就将其设置为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