仅在父状态更新后如何接收道具?

Posted

技术标签:

【中文标题】仅在父状态更新后如何接收道具?【英文标题】:How to receive props only after state of parent has updated? 【发布时间】:2020-01-16 07:46:09 【问题描述】:

我正在尝试构建一个小的天气小部件,其中用户的地理位置被捕获在一个组件中,然后传递给一个子组件,该组件获取天气数据(基于位置),然后最终呈现一个图标,指示当前的天气状况。

我将经度和纬度状态作为道具传递给我的 WeatherWidget。不幸的是,WeatherWidget 也接收到初始状态 null。我怎样才能避免这种情况?

感谢您的帮助!

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"



    

【问题讨论】:

【参考方案1】:

一种选择是有条件地在父组件中渲染:

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;
  

【讨论】:

【参考方案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)
    

【讨论】:

以上是关于仅在父状态更新后如何接收道具?的主要内容,如果未能解决你的问题,请参考以下文章

高阶组件状态正在正确更新,但接收道具的包装组件不会在状态更改时重新渲染

React 子组件在父组件中更新状态后如何将其重置回原始状态

在父组件的状态更改中重新呈现子组件

如何在父状态更改后重建子项(和重放动画)

从 redux 更改状态后如何以及何时调用反应组件方法

如何使用 Relay QueryRenderer 道具更新状态