React-autosuggest: Clarifying behavior of `shouldRenderSuggestions`

Created on 8 Dec 2017  路  5Comments  路  Source: moroshko/react-autosuggest

Are you reporting a bug? Yes

  • Codepen: https://codepen.io/oyeanuj/pen/vWqaQW

  • Steps

    1. Focus on the input field
    2. Type c, and wait for suggestions to appear
    3. Notice the dropdown with custom footer.
    4. Delete c and instead enter d
    5. Dropdown doesn't open. Note that shouldRenderSuggestions is true at this point.

    Observed behaviour: Suggestions' container are closed

    Expected behaviour: Suggestions' container should stay open, since shouldRenderSuggestions is returning true.

Essentially, I am trying to show a catch-all situation where if no results exist, the user can do something else. But the container isn't opening when shouldRenderSuggestions is true unless results exists. That seems like contradictory behavior.

Thoughts?

And as always, thank you for keeping this library going!

Most helpful comment

@oyeanuj I think I suffered from the same problem as you, and was able to solve this using the current Autosuggest solution.

In the below code, I ensure that the suggestions container always displays. Then, I use the renderSuggestionsContainer method to render any suggestions (when they exist), and if they don't exist AND the query is > 1, I render something else in it's place. Now, I get the desired effect of seeing "Add New Member" when no suggestions are returned.

.react-autosuggest__suggestions-container {
      display: block;
    }

.react-autosuggest__suggestions-container--open {
      display: block;
    }
  renderSuggestionsContainer = ({ containerProps, children, query }) => {
    return (
      <div {...containerProps}>
        <div className="suggestions-container">
          <div className="children">{children}</div>
          {!children && query.length > 1 ? (
            <div className="add-member-button">Add New Member</div>
          ) : null}
        </div>
      </div>
    );
  };

  shouldRenderSuggestions = () => {
    return true;
  };

All 5 comments

@moroshko Should this line here be an 'OR' rather than 'AND' ?
https://github.com/moroshko/react-autosuggest/blob/b5373a91fba3f7e9f941d9ae492dd097a91bd7a9/src/Autosuggest.js#L306-L310

shouldRenderSuggestions seems to me the one way to make the container behave like a controlled component if it wasn't being overwritten above.

@oyeanuj A simple npm t reveals that changing 'OR' to 'AND' will cause some tests to fail. I haven't dug into the failures though. Feel free to do that and challenge whether the tests are valid.

Historically, when we didn't have renderSuggestionsContainer, there was no good reason to render the suggestions container when suggestions.length === 0.

But, I agree, now that we do have renderSuggestionsContainer, it makes sense to allow this.

Here is one solution that comes to mind:

willRenderSuggestions(props) {
  const {
    suggestions,
    renderSuggestionsContainer,
    inputProps,
    shouldRenderSuggestions
  } = props;
  const { value } = inputProps;

  return (
    (suggestions.length > 0 ||
      renderSuggestionsContainer !== defaultRenderSuggestionsContainer) &&
    shouldRenderSuggestions(value)
  );
}

The problem is that this is not enough. The underlying react-autowhatever will render the suggestions container but will not consider it open (you can see it hidden in the DOM).

We could try a similar solution here, and change this line to be:

const isOpen = (
  renderedItems !== null || 
  renderItemsContainer !== defaultRenderItemsContainer
);

I haven't tested this (struggling to find time), but I believe this should be enough.

If you are onboard with this solution, would you be able to test it and submit the PRs?

@oyeanuj or @moroshko were you able to make any progress here? If not, I can take a look and potentially raise a PR. Just don't want to do work if it was already done.

@caguthrie I still hadn't made it back to this issue to make a PR, so thank you for making the PR 馃憤 Hope we can get this merged soon!

@oyeanuj I think I suffered from the same problem as you, and was able to solve this using the current Autosuggest solution.

In the below code, I ensure that the suggestions container always displays. Then, I use the renderSuggestionsContainer method to render any suggestions (when they exist), and if they don't exist AND the query is > 1, I render something else in it's place. Now, I get the desired effect of seeing "Add New Member" when no suggestions are returned.

.react-autosuggest__suggestions-container {
      display: block;
    }

.react-autosuggest__suggestions-container--open {
      display: block;
    }
  renderSuggestionsContainer = ({ containerProps, children, query }) => {
    return (
      <div {...containerProps}>
        <div className="suggestions-container">
          <div className="children">{children}</div>
          {!children && query.length > 1 ? (
            <div className="add-member-button">Add New Member</div>
          ) : null}
        </div>
      </div>
    );
  };

  shouldRenderSuggestions = () => {
    return true;
  };
Was this page helpful?
0 / 5 - 0 ratings

Related issues

avjpl picture avjpl  路  12Comments

felixhammerl picture felixhammerl  路  15Comments

acthp picture acthp  路  10Comments

approots picture approots  路  14Comments

fatso83 picture fatso83  路  12Comments