biziclop
biziclop

Reputation: 49724

How to refresh dropdown in ReactJS?

I've got a basic dropdown setup like this:

(Obviously in the real world fetchValues() would go to a server):

import ReactDOM from "react-dom";
import React, { useState, useEffect } from "react";

const fetchValues = () => Promise.resolve(["option1", "option2"]);

function Dropdown(props) {
  const [options, setOptions] = useState(null);
  useEffect(() => {
      props.fetchValues().then(setOptions);
  }, [props.fetchValues]);

  return <select>{options && options.map(o => <option>{o}</option>)}</select>;
}

ReactDOM.render(
  <Dropdown fetchValues={fetchValues} />,
  document.getElementById("root")
);

This works great, but only once. What is an idiomatic way to make the component call fetchValues() again when something else changes in my application? (It's also acceptable if fetchValues() is called on every render, except the ones triggered by the effect itself.)

Upvotes: 1

Views: 4178

Answers (3)

alaa tohamy
alaa tohamy

Reputation: 21

useEffect last parameter is the dependency list (when any value changes inside this list it will call useEffect again), you just include [props.fetchValues] so useEffect will be called only when fetchValues changes.

you have 2 options:

  • pass the other props throw (state management like redux, context api, or props throw parents) and add it to the list, like this

    useEffect(() => {
     props.fetchValues().then(setOptions);
    }, [props.fetchValues, props.otherProps]);
    
  • leave the dependency null (do not write empty list), and in this state it will be called whenever anything change in your app, like this

     useEffect(() => {
     props.fetchValues().then(setOptions);});
    

Upvotes: 2

Maxwell s.c
Maxwell s.c

Reputation: 1668

useEffect(() => {
      props.fetchValues().then(setOptions);
  }, [props.fetchValues, SOMETHING]);

where SOMETHING is the thing that changes in your application that may trigger the fetch (the best is get this value from props or context)

Upvotes: 1

biziclop
biziclop

Reputation: 49724

For the record, the solution I went with, the one that appears the cleanest was to abandon the idea altogether and just pass the options themselves as props, leaving fetching (and caching) to a custom hook used by a component much higher up the hierarchy.

As far as I can tell, the reason my original idea didn't work neatly is that I broke the single responsibility principle.

Upvotes: 1

Related Questions