Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Focus an input after an action is dispatched #266

Closed
elado opened this issue Jan 25, 2016 · 5 comments
Closed

Question: Focus an input after an action is dispatched #266

elado opened this issue Jan 25, 2016 · 5 comments

Comments

@elado
Copy link

elado commented Jan 25, 2016

I have a button that dispatches an action that toggles a boolean in the store. As a result, an input is rendered in the component. I want to focus on that input after the button is clicked, but I can't do it immediately because the this.refs is not updated until the new props are received.

If this is handled in componentDidUpdate, all subsequent action will keep triggering the focus, so that's not a good solution.

  componentDidUpdate() {
    const { isComposing } = this.props

    if (isComposing) {
      this.refs.composer.focus()
    }
  }

Example: http://jsbin.com/nerexi/2/edit?js,console,output

Another potential solution is a combination of focusing from the componentDidMount and also from the button callback: http://jsbin.com/viwive/3/edit?js,console,output

Not a big fan of this as it seems like the container component's job to focus.

However, using setState and its callback actually allows to access the ref, as it fires after render happens: http://jsbin.com/yiputo/1/edit?js,console,output (cleanest solution, I believe, despite the use of state)

This question relates to any UI forced interaction that needs to happen after an action but can't be in render. Another example would be scrolling to an element to bottom after an action is dispatched.

@elado
Copy link
Author

elado commented Jan 25, 2016

Looks like ref with a callback is a nicer solution, as it leaves handling the focus to the parent.

render() {
  ...<Composer ref={c => this._composer = c; c && c.focus()} />
}

onCompose() {
  //... dispatch action
  this._composer && this._composer.focus() // for cases Composer is already visible and button clicked
}

@gaearon
Copy link
Contributor

gaearon commented Jan 26, 2016

I'd do something like

  componentDidUpdate(prevProps) {
    const { isComposing } = this.props
    const { isComposing: wasComposing } = prevProps

    if (!wasComposing && isComposing) {
      this.refs.composer.focus()
    }
  }

I agree callback refs are nice: #270 (comment). However I'd rather use them for DOM nodes than for instances. Best not to expose instances or use their methods.

@bvmCoder
Copy link

bvmCoder commented Aug 9, 2017

const { isComposing: wasComposing } = prevProps

Could you please Explain the above line...

@markerikson
Copy link
Contributor

@bvmCoder : not the best place to ask that question, but I'll go ahead and answer. That is ES6 "destructuring assignment". It's taking the prevProps.isComposing variable, and creating a local variable named wasComposing.

For more info, see these links on ES6 syntax and features.

@timramone
Copy link

const { wasComposing: isComposing } = prevProps maybe? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants