在ref中将ref传递给parent

时间:2019-01-13 20:09:16

标签: javascript reactjs

我有一个小应用程序,带有输入,并根据搜索值显示特定城市的天气。不过我被困在某个点上。这个想法是,一旦您搜索城市,它就会隐藏文本输入和搜索按钮,并显示一些天气信息和另一个搜索按钮以搜索新城市。我的问题是,当我再次单击搜索时,我想专注于搜索框。我希望这是有道理的。我读到,执行此操作的理想方法是使用refs。我这样接线:

class WeatherForm extends React.Component {
  constructor(props) {
    super(props);
    this.city = React.createRef();
  }

  componentDidMount() {
    this.props.passRefUpward(this.city);
    this.city.current.focus();
  }

  render() {
    if (this.props.isOpen) {
      return (
        <div className={style.weatherForm}>
          <form action='/' method='GET'>
            <input 
              ref={this.city} 
              onChange={this.props.updateInputValue} 
              type='text' 
              placeholder='Search city' 
            />
            <input 
              onClick={e => this.props.getWeather(e)} 
              type='submit' 
              value='Search' 
            /> 
          </form>
        </div>
      )
    } else {
      return (
        <div className={style.resetButton}>
          <p>Seach another city?</p>
          <button 
            onClick={this.props.resetSearch}>Search
          </button>
        </div>
      );
    }
  }
}

通过此操作,我可以使用this.state.myRefs.current.value;将该引用传递给父级以在搜索中使用,这很好用,但是当我尝试在其他函数中引用this.state.myRefs.current时使用{{1 }},它返回.focus()

null

这是因为我要隐藏并显示基于搜索点击的不同组件吗?我已经阅读了很多关于SO的文章,但是我仍然无法破解。任何帮助表示赞赏。我将在下面包含完整的代码。要在此处完整查看,请参见git repo:https://github.com/DanDeller/tinyWeather/blob/master/src/components/WeatherMain.js

resetSearch = () => {
    console.log(this.state.myRefs.current); // <- returns null

    this.setState({
      isOpen: !this.state.isOpen,
      details: [],
      video: []
    });
  }

2 个答案:

答案 0 :(得分:1)

您尝试从DOM中实现卸载的组件,因此无法捕获引用。如果将此代码放置为WeatherForm组件的渲染函数而不是它的渲染函数,则可以捕获引用。因为我只是隐藏它,而不是从DOM中删除。

  render() {
        return (
            <div>
                <div className={style.weatherForm}
                     style={this.props.isOpen ? {visibility:"initial"} :{visibility:"hidden"}}>
                    <form action='/' method='GET'>
                        <input
                            ref={this.city}
                            onChange={this.props.updateInputValue}
                            type='text'
                            placeholder='Search city'
                        />
                        <input
                            onClick={e => this.props.getWeather(e)}
                            type='submit'
                            value='Search'
                        />
                    </form>
                </div>
                <div className={style.resetButton} style={this.props.isOpen ? {visibility:"hidden"} :{visibility:"initial"}}>
                    <p>Seach another city?</p>
                    <button
                        onClick={this.props.resetSearch}>Search
                    </button>
                </div>
            </div>
        )
   }

答案 1 :(得分:0)

console.log(this.state.myRefs.current)返回null,因为它是对输入dom元素的引用,该元素不存在,因为当前“天气”表单正在显示“搜索另一个城市”以及一个重置按钮。

在重置功能状态下更改,这会导致对WeatherForm组件的prop isOpen进行更改。现在,屏幕将显示输入字段以及搜索按钮。

组件更新后,将调用ComponentDidUpdate生命周期方法。

请在WeatherForm中添加ComponentDidUpdate生命周期方法,然后添加, 方法主体中的this.city.current.focus()。

不需要将dom元素的引用传递给父元素,因为它不被认为是一种好习惯。

编辑1:-

仅当prop(isOpen)为true时才需要将输入字段设置为焦点,因为只有在安装了输入字段时,我们才会引用该输入字段。

ComponentDidUpdate(){
if(this props.isOpen)
this.city.current.focus
}

链接到生命周期方法:- https://reactjs.org/docs/react-component.html#componentdidupdate

希望这会有所帮助,

干杯!