【问题标题】:How to assign a value to the state with a promise prior to the render method executing如何在渲染方法执行之前为状态赋值
【发布时间】:2019-05-04 04:35:28
【问题描述】:

编辑:

Here is a working jsComplete(使用 chrome)我将 JSON 分配给状态,而不是进行 api 调用。不过,我正在尝试对 api 调用做同样的事情。

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

locoData 永远不会被分配,console.log(resp.data); 在渲染方法之后执行。我是新手,刚刚赶上 JavaScript 中的新功能,例如 Promise,这真的让我很困惑。我在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"}

【问题讨论】:

  • 您好,我认为您最好使用 lifeCicle componentDidMount 提出您的请求。在 de render() 中,您有 resources,但从未声明过该变量。另一个很好的技巧是尝试使用析构函数,用于状态和道具。
  • 还要研究条件渲染,以便在数据加载后仅渲染元素/组件。 reactjs.org/docs/conditional-rendering.html
  • 这里使用的最佳解决方案是使用加载器进行条件渲染。
  • @JuniusL. 有没有什么地方可以指点我,有一个例子,我不完全明白这是什么意思。
  • 查看我创建的这个小例子stackblitz.com/edit/react-ukpsej

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


【解决方案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

【讨论】:

  • 太棒了,我为条件创建了一个 Loader 类,它工作得很好,我看到你在这里使用条件状态属性做了什么,并在 render() 返回中使用它。现在进入下一部分,使用 NOAA api 传递坐标并获取当前天气。然后我将为用户添加输入以输入地址。我认为这将是一个很好的挑战来练习我正在学习的东西。感谢您的帮助!
【解决方案2】:

我不知道这是否是您问题的正确答案。 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 hooks 的新功能,在这种情况下,与 componentWillMount 相同

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

PS: 只需使用钩子,旧的反应循环已被弃用

【讨论】:

  • 我尝试使用componentWillMount(),但没有成功。我会阅读你的链接。
  • 什么是resp.data?
  • @Gianmarco 这是回复
  • @Gianmarco 感谢您的输入,但条件渲染是解决方案。我仍然会阅读钩子,因为它看起来像我需要知道和理解的东西。我在学习复数视力的课程中提到了这一点。
猜你喜欢
  • 1970-01-01
  • 2021-01-18
  • 2021-07-20
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 2020-12-12
  • 1970-01-01
  • 2017-11-11
相关资源
最近更新 更多