beta programmers
beta programmers

Reputation: 653

Rendering part of a React function component after async call gets completed

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>
    );
}

Upvotes: 3

Views: 5963

Answers (2)

Fraction
Fraction

Reputation: 12993

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.

Upvotes: 8

iqbal125
iqbal125

Reputation: 1431

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>

Upvotes: -1

Related Questions