3

I'm using material-ui with a React function component and using its Autocomplete component. I customized it and whenever I change the text in input field, I expect the component to render new search result.

callAPI("xyz")

I'm calling the API in the action and using the xyz parameter, I'm calling the dispatch method from this function component.

Problem here is, when the component makes the call, it is supposed to wait for the API response and then render the result, but it gets an unresolved promise, so it fails rendering.

<Paper square>
    {callAPI("xyz").results.map(
        result => console.log(result);
    )}
</Paper>

as results are a unresolved promise, it will fail to map. I need some way to call the map only once data is available, or show some text before data is there and then change once data is fetched.

Any suggestions to correct this code will be very helpful.

EDIT:

function IntegrationDownshift() {
    return (
        <div>
            <Downshift id="downshift-simple">
                {({
                    getInputProps,
                    getItemProps,
                    getMenuProps,
                    highlightedIndex,
                    inputValue,
                    isOpen,
                    selectedItem
                }) => (
                    <div>
                        {renderInput({
                            fullWidth: true,
                            InputProps: getInputProps({
                                placeholder: "Search users with id"
                            })
                        })}

                        <div {...getMenuProps()}>
                            {isOpen ?
                                 <Paper square>
                                {callAPI(inputValue).users.map(
                                    (suggestion, index) =>
                                        renderSuggestion({
                                            suggestion,
                                            index,
                                            itemProps: getItemProps({
                                                item:
                                                    suggestion.userName
                                            }),
                                            highlightedIndex,
                                            selectedItem
                                        })
                                )}
                            </Paper>  
                             : null}
                        </div>
                    </div>
                )}
            </Downshift>
        </div>
    );
}
4
  • Dispatch an action for triggering loader or some text that the data is loading, once it get resolved dispatch the action for turning of the loader and setting the data. In your jsx you can write a ternary check if loader is true render the loader component else render the data Commented Jun 2, 2019 at 18:16
  • @DILEEPTHOMAS Can you please provide any psuedo code or sample for your example please Commented Jun 2, 2019 at 18:26
  • can you provide some more code, i think paper is a customized component. So on change you will be calling a props and the dispatch is done in the parent component Commented Jun 2, 2019 at 18:29
  • @DILEEPTHOMAS added additional code for reference, you can see the callAPI method is taking inputValue and returns the Object with users. I want to apply map on that and call another render. But when it loads initially, the <Paper> renders without the data, as the promise is still unresolved, it fails with map. Commented Jun 2, 2019 at 18:41

2 Answers 2

8

React 16.8 introduces Hooks:

Hooks are functions that let you “hook into” React state and lifecycle features from function components.

so you have useState() which you can declare a state variable with an empty array and call your API in the useEffect() to populate the state when you get the response from the API:

function App() {

  const [data, setData] = useState([]);

  useEffect(() => {
    callAPI("xyz").then(result => {
      setData(result);
    })  
  }, []);

  if(!data.length) return (<span>loading...</span>);

  return (
    <Paper square>
        {data.map(
            result => console.log(result);
        )}
    </Paper>
  );
}

More about hooks: https://reactjs.org/docs/hooks-intro.html.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for introducing hooks, this might be helpful
-1

Easiest way to handle this is with a ternanry expression And also its best practice to call your API request in a lifecycle method and then save the result in local state.

componentDidMount() {
    callAPI("xyz").results.map(
        result => this.setState(result);

}

<Paper square>
    {this.state.results ?
      this.state.results.map(
        result => console.log(result);
      : <p> Loading... </p>
    )}
</Paper>

3 Comments

But as I said it is a stateless functional component, so I can't use lifecycle methods and also localstate
You are making an API request here, why would you not make it a stateful component?
Though stateless components are for rendering purpose, as per my minimal knowledge, there is no necessity for it to be stateful if it makes an API cal, unless it maintains the state by storing the API data for further reference. I'm ready to get corrected if I'm wrong. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.