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

[AutoComplete] Issue with the controlled behavior / clear #2615

Closed
dcsan opened this issue Dec 21, 2015 · 15 comments · Fixed by #5685
Closed

[AutoComplete] Issue with the controlled behavior / clear #2615

dcsan opened this issue Dec 21, 2015 · 15 comments · Fixed by #5685
Labels
bug 🐛 Something doesn't work component: autocomplete This is the name of the generic UI component, not the React module!

Comments

@dcsan
Copy link

dcsan commented Dec 21, 2015

I have an autocomplete field which uses

        searchText = {this.state.searchText}

like this;

          <AutoComplete
            floatingLabelText='agent input'
            ref='agentInput'
            hintText="type response"
            multiLine = {true}
            fullWidth = {true}
            searchText = {this.state.searchText}
            onNewRequest={this.sendAgentInput}
            dataSource={this.agentCommands}
          />

but when I update the

 this.setState({searchText: null })

in the onNewRequest func
it will clear the autoComplete once, but not the second time.
it seems some internal caching happens?

how to call internal methods of the MUI components?

mat-ui components more general question:
Is there a way to call the methods on that object directly like setValue?
https://github.com/callemall/material-ui/blob/master/src/auto-complete.jsx#L244-L248

I tried something like

    var field = (
        <AutoComplete 
          searchText = {this.state.searchText}
          dataSource={this.agentCommands}
      />
    );

    field.props.setValue("");

but that doesn't work. Given an instance of a component how would I access its methods?

this is a more general question, i could add it to the docs if someone could illuminate me.

@alitaheri
Copy link
Member

how to call internal methods of the MUI components?

This is rather react related not material-ui

you cannot call methods on elements rather on instances referenced with ref, for more information please read through this awesome blog post by the react team here.

@joncursi
Copy link

@alitaheri how would you suggest we get / set the ref on the autocomplete input given the only API we have access to is <AutoComplete />?

@alitaheri
Copy link
Member

@joncursi
Copy link

joncursi commented May 25, 2016

@alitaheri I guess what I'm trying to say is that Material UI does not expose the <input> element for us to assign a ref. It's bundled underneath the <AutoComplete /> component. How do we pass the ref through AutoComplete to input?

@alitaheri
Copy link
Member

alitaheri commented May 25, 2016

right right. You can't do that but you can use setValue and getValue the same way see here although calling them will warn you. I would advise against it too, you should follow react's idiomatic flow of data. use searchText prop instead of calling imperative methods.

@alexprice1
Copy link

Hey, I am trying to use the props searchText, and on onNewRequest I set my searchText to (empty string) but AutoComplete still shows what the string was prior to me setting the searchText

@alexprice1
Copy link

@alexprice1
Copy link

What if we do something like this there:

    const currentSearchText = this.state.searchText;
    this.timerTouchTapCloseId = setTimeout(() => {
      if(this.state.searchText === currentSearchText) {
        this.setState({
          searchText: searchText,
        });
      }
      this.close();
      this.timerTouchTapCloseId = null;
    }, this.props.menuCloseDelay);

@jlroettger
Copy link

jlroettger commented Jul 20, 2016

Can we just add a boolean prop that, when set to true, will prevent the asynchronous setState inside handleItemTouchTap?

Edit: actually, I don't think that solution would fully address the issue.

@alexprice91 explains the problem above. Even if you are controlling the AutoComplete with the searchText prop, that asynchronous setState still gets fired. In that situation you end up with searchText (the prop in a controlled use) being different than searchText (the state), which is no bueno.

I don't really like the if(this.state.searchText === currentSearchText) { solution, since it doesn't resolve the searchText state and prop incongruency. I think we should just get rid of this setState in its entirety. If the user wants to fill in the <input> whenever an option is clicked, it's trivial for them to handle it themselves using onNewRequest and the searchText prop. We shouldn't be forcing this behavior considering A) how simple it is to implement in userland and B) how difficult / janky it is to override when it's baked in.

@greypants
Copy link

A short-term workaround is to give your auto complete component a ref, then manually call setState to reset searchText.

this.refs.autoComplete.setState({ searchText: ''})

@petermikitsh
Copy link
Contributor

Thanks @greypants! Your approach worked for me.

@lucasbento lucasbento added the component: text field This is the name of the generic UI component, not the React module! label Nov 13, 2016
@oliviertassinari oliviertassinari added component: AutoComplete and removed component: text field This is the name of the generic UI component, not the React module! labels Nov 26, 2016
@oliviertassinari oliviertassinari changed the title cannot clear the autoComplete field [AutoComplete] Issue with the controlled behavior / clear Nov 26, 2016
@oliviertassinari oliviertassinari added bug 🐛 Something doesn't work and removed new feature New feature or request labels Nov 26, 2016
@oliviertassinari
Copy link
Member

oliviertassinari commented Nov 26, 2016

Even if you are controlling the AutoComplete with the searchText prop, that asynchronous setState still gets fired.

@jlroettger I completely agree, that setState shouldn't be called at all when the component is controlled.
That issue has been discussed here #5627.
However, In order not to introduce breaking change, I think that the following change would address the issue:

  handleItemTouchTap = (event, child) => {
    const dataSource = this.props.dataSource;

    const index = parseInt(child.key, 10);
    const chosenRequest = dataSource[index];
    const searchText = this.chosenRequestText(chosenRequest);
+
+    this.setState({
+      searchText: searchText,
+    });
+    this.props.onUpdateInput(searchText, this.props.dataSource, {
+      type: 'selected',
+    });

    this.timerTouchTapCloseId = setTimeout(() => {
      this.timerTouchTapCloseId = null;
-
-      this.setState({
-        searchText: searchText,
-      });
      this.close();
      this.props.onNewRequest(chosenRequest, index);
    }, this.props.menuCloseDelay);
  };

@itsmeek
Copy link

itsmeek commented Aug 29, 2017

For some reason, this issue still persisted for me. There are different arguments to the third parameter depending on whether you're typing or selecting a menu item. I just honed in on that action to only set the state when it is a change event
const handleUpdateInput = (attributeName, _, { source }) => { if (source === 'change') { this.setState({ attributeName }) } }

@sirajalam049
Copy link
Contributor

As the components are now functional, setState is no longer working, do we have any alternative solution?

@mui mui locked as resolved and limited conversation to collaborators Apr 4, 2020
@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 4, 2020

@sirajalam049 Material-UI can still be used in class components, only our demos can't. This is very handy for the legacy parts of your codebase so you don't have to migrate them to hooks (assuming you write all new features in hooks).

@oliviertassinari oliviertassinari added the component: autocomplete This is the name of the generic UI component, not the React module! label Apr 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug 🐛 Something doesn't work component: autocomplete This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging a pull request may close this issue.