在条件渲染中使用refs

时间:2018-06-23 16:12:41

标签: javascript reactjs reference

我在参考和条件渲染方面遇到问题。 单击按钮标签时,我想聚焦输入标签。 基本上,我有这个简化的代码。

class App extends React.Component {
  textInput
  constructor(props) {
    super(props)
    this.state = {isEditing: false}
    this.textInput = React.createRef()
  }

    onClick = () => {
        this.setState({isEditing: !this.state.isEditing})
        this.textInput.current.focus();
    }
  render () {
    let edit = this.state.isEditing ?
        (<input type="text" ref={this.textInput} />)
        : ""
    return (
      <div>
            <button onClick={this.onClick}>lorem </button>
            {edit}
      </div>
    );
  }
}

当我单击按钮时,显示输入标签,但参考文献textInput仍设置为null。因此我无法集中输入。

我找到了一些解决方法,例如:

    在输入代码中
  • 设置autoFocus属性
  • isEditing == false时使用CSS隐藏输入标签

但这实际上是一个非常基本的模式,我想知道是否有一个干净的解决方案。

谢谢

2 个答案:

答案 0 :(得分:4)

TL; DR:

更改此:

this.setState({isEditing: !this.state.isEditing})
this.textInput.current.focus();

对此:

this.setState(state => ({isEditing: !state.isEditing}), () => {
    this.textInput.current.focus();    
});

详细信息:

React遇到了很多人遇到的一个常见问题,即设置状态是同步的。不是。调用setState时,您是请求,要求React更新状态。实际状态更新稍后发生。这意味着在setState调用之后,edit元素尚未创建或呈现,因此引用指向null

来自the docs

  

setState()使更改进入组件状态,并告诉React该组件及其子组件需要使用更新后的状态重新呈现。这是用于响应事件处理程序和服务器响应而更新用户界面的主要方法。

     

setState()视为请求而不是立即命令来更新组件。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不能保证状态更改会立即应用。

     

setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用this.state之后立即阅读setState()是一个潜在的陷阱。相反,请使用componentDidUpdatesetState回调(setState(updater, callback)),可以保证在应用更新后会触发二者之一。

答案 1 :(得分:0)

非常感谢您的回答@rossipedia。我想知道我是否可以用钩子做到这一点。

显然,您不能像setState一样将第二个参数传递给useState setter。但是您可以像这样使用useEffect(请注意useEffect中的第二个参数):

const [isEditing, setIsEditing] = React.useState(false);
React.useEffect(() => {
    if (isEditing) {
        textInput.current.focus();
    }
}, [isEditing]);

const handleClick = () => setIsEditing(isEditing);

它奏效了! ;)

来源:https://www.robinwieruch.de/react-usestate-callback/