Как присвоить значение состоянию с помощью обещания до выполнения метода рендеринга

РЕДАКТИРОВАТЬ:

Вот рабочий jsComplete (используйте хром), где я назначаю JSON состоянию вместо создания api вызов. Я пытаюсь сделать то же самое с вызовом api.

Как присвоить значение свойству состояния locoData перед запуском метода render()?

locoData никогда не назначается, а console.log(resp.data); выполняется после метода рендеринга. Я новичок в реакции и просто знаком с новыми функциями JavaScript, такими как обещания, и это меня действительно сбивает с толку. Я выполняю этот код в jsComplete

Если я назначу JSON состоянию вместо попытки использовать метод axios.get, он будет работать нормально. Ответ JSON находится внизу.

Я удалил свой ключ карты Bing.

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

person Popo    schedule 04.05.2019    source источник
comment
Привет, я думаю, лучше вы сделаете свой запрос, используя lifeCicle componentDidMount. Внутри de render () есть resources, но эта переменная никогда не объявлялась. Еще один хороший совет: попробуйте использовать деструктор для состояния и свойств.   -  person Edison Junior    schedule 04.05.2019
comment
Также изучите условный рендеринг, чтобы отображать элементы / компоненты только после загрузки данных. reactjs.org/docs/conditional-rendering.html   -  person Alexander Staroselsky    schedule 04.05.2019
comment
Лучшее решение здесь - условный рендеринг с загрузчиком.   -  person Junius L.    schedule 04.05.2019
comment
@ JuniusL. Где-то вы можете указать мне на пример, я не совсем понимаю, что это значит.   -  person Popo    schedule 04.05.2019
comment
посмотрите этот небольшой пример, который я создал stackblitz.com/edit/react-ukpsej   -  person Junius L.    schedule 04.05.2019
comment
@JuniusL. спасибо, мне понадобится немного времени, чтобы это переварить.   -  person Popo    schedule 04.05.2019
comment
use chrome - почему?   -  person Jaromanda X    schedule 04.05.2019


Ответы (2)


Вам нужно использовать условный рендеринг, установить для переменной значение true, например state = { isLoading: true }, когда вы получаете данные из api, вы устанавливаете его в false.

руководство по условному рендерингу

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>
    );
  }
}

Демо

person Junius L.    schedule 04.05.2019
comment
Потрясающе, я создал класс Loader для условия, и он отлично работает, и я вижу, что вы здесь делаете со свойством условного состояния и используете его в return () render (). Теперь перейдем к следующей части, чтобы использовать API NOAA для передачи координат и получения текущей погоды. Затем я собираюсь добавить данные, чтобы пользователь мог ввести адрес. Я подумал, что это будет хорошим испытанием для практики того, что я изучаю. Спасибо за помощь! - person Popo; 04.05.2019

Не знаю, правильный ли это ответ на вашу проблему. В 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
    }

который запускается перед монтированием компонента. Второе решение - использовать новую функцию перехватчиков реакции, в данном случае это то же самое, что и componentWillMount.

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

PS: Просто используйте хуки, старый цикл реагирования больше не поддерживается

person Gianmarco    schedule 04.05.2019
comment
Я безуспешно пытался использовать componentWillMount(). Я буду читать по вашим ссылкам. - person Popo; 04.05.2019
comment
что такое соотв. данные? - person Gianmarco; 04.05.2019
comment
stackoverflow.com/questions/49206280/ - person Junius L.; 04.05.2019
comment
@Gianmarco, это ответ - person Junius L.; 04.05.2019
comment
о, так что используйте только крючки - person Gianmarco; 04.05.2019
comment
@Gianmarco JSON из resp.data находится внизу вопроса, я также обновил вопрос с помощью jsComplete.com, где я использую JSON вместо вызова api, который работает, но не то, что мне нужно. - person Popo; 04.05.2019
comment
здесь крючки не нужны. - person Junius L.; 04.05.2019
comment
@JuniusL. спасибо за ссылку об устаревшем методе. - person Popo; 04.05.2019
comment
а также нам трудно предложить решение, если мы не знаем, что возвращается из API. - person Junius L.; 04.05.2019
comment
@JuniusL. JSON из API находится внизу вопроса. Вот пример, в котором просто используется JSON вместо вызова api jscomplete.com/playground/s267152 - person Popo; 04.05.2019
comment
@Gianmarco Спасибо за ввод, но условный рендеринг был решением. Я все еще собираюсь прочитать о крючках, поскольку это похоже на то, что мне нужно знать и понимать. Об этом упоминалось в курсе, который я изучал во множественном числе. - person Popo; 04.05.2019