Как получить реквизит только после обновления состояния родителя?

Я пытаюсь создать небольшой погодный виджет, где геолокация пользователя фиксируется в одном компоненте, а затем передается дочернему компоненту, который извлекает данные о погоде (в зависимости от местоположения), а затем в конечном итоге отображает значок, указывающий текущую погоду. условия.

Я передаю состояние долготы и широты в качестве свойств своего WeatherWidget. К сожалению, WeatherWidget также получает нулевое начальное состояние. Как мне этого избежать?

Спасибо за помощь!

class GetGeolocation extends Component{
    constructor(){
        super();
        this.state = {
            lngt: null,
            latd: null
        }

    }

    componentDidMount(){
        this.getLocation()
    }

    getLocation = () => {
        if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(position => {
                this.setState({lngt: position.coords.longitude.toFixed(4)});
                this.setState({latd:position.coords.latitude.toFixed(4)});
             }    
            );
        };
    }

    render(){
        return (
            <>
            <WeatherWidget lngt = {this.state.lngt} latd = {this.state.latd} />
            </>
        )
    }

class WeatherWidget extends Component{
    constructor(props){
        super(props);
        this.state = {
            weather:[]
        }
    }
    componentWillReceiveProps(nextProps){
        this.getWeather(nextProps)
    }

    getWeather = (location) => {

        console.log(location) 
        // The console logs twice:
        // First:
        //{lngt: "-12.3456", latd: null}
        //Then, the correct values:
        //{lngt: "-12.3456", latd: "78,9999"}



    }

person suuuriam    schedule 15.09.2019    source источник


Ответы (2)


Не используйте componentWillReceiveProps, это будет устаревшим в более поздних версиях React.

Но также вы можете просто настроить условную логику в своих методах жизненного цикла, чтобы определить, какой код выполнять.

componentWillReceiveProps(nextProps){
    //condition says if both value are truthy then run code.
    if(nextProps.lngt && nextProps.latd){
         this.getWeather(nextProps)
    }
}

Вы также можете использовать componentDidUpdate()

componentDidUpdate(){
    //condition says if both value are truthy then run code.
    if(this.props.lngt && this.props.latd){
         this.getWeather(this.props)
    }
}
person Cool Guy    schedule 15.09.2019

Один из вариантов - условный рендеринг в родительском компоненте:

class GetGeolocation extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      lngt: null,
      latd: null
    };
  }

  componentDidMount() {
    this.getLocation();
  }

  getLocation = () => {
    // Simulate the network request
    setTimeout(() => this.setState({ lngt: 100 }), 1000);
    setTimeout(() => this.setState({ latd: 100 }), 1000);
  };

  render() {
    const { lngt, latd } = this.state;
    if (!lngt || !latd) return null;

    return <WeatherWidget lngt={lngt} latd={latd} />;
  }
}

class WeatherWidget extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      weather: []
    };
  }

  componentDidMount() {
    this.getWeather(this.props);
  }

  getWeather = location => {
    console.log(location);
  };

  render() {
    return null;
  }
}
person skovy    schedule 15.09.2019