0

I have a file that stores an array of objects. I have a component that fetches data from this file then render the list. The file could be updated somewhere else, I need the component to be updated if the file is modified. I have following code example

const header = () => {
  const [list, setList] = useState([]);
  
  // fetch 
  useEffect(() => {
    const loadList = async () => {
      const tempList = await getList("/getlist"); // get call to fetch data from file
      setList(tempList);
    };
    loadList ();
  }, [list]);

  // function to render content
  const renderList = () => {
    return list.map(obj => (
      <div key={obj.name}>
        {obj.name}
      </div>
    ));
  };
  
  return (
    <div>{renderList()}</div>
  )
}

// get call
router.get('/getlist', 
  asyncWrapper(async (req, res) => {
    const result = await getList();
    res.status(200).json(result).end();
  })
);

const getList= async () => {
  const list = JSON.parse(await fs.readFile(listPath));
  return list;
}

Code has been simplified. If I remove the list from useEffect, then it will only render once and will never update unless I refresh the page. If I include list there, loadList() will get called constantly, and component will get re-rendered again and again. This is not the behavior I want. I am just wondering without making header component async component, how do I only re-render this component when the file is changed?

Thank you very much.

15
  • Can you use Class Components? Commented Nov 12, 2020 at 21:52
  • No, I need to use funtional component. Commented Nov 12, 2020 at 21:55
  • What happens if you give an empty dependency array and ignoring the errors, does it work? Commented Nov 12, 2020 at 21:55
  • No, I tried that. It does not work. If it's empty, it will render the first time, but will never update the component with new list if the file is changed. Commented Nov 12, 2020 at 21:56
  • Do you mean that the file gets modified from the server-side and you need to detect a change? Commented Nov 12, 2020 at 21:57

1 Answer 1

1

There are two approaches you can take to this:

Polling

Request the URL on an interval, and clear it when the component is unmounted.

Replace loadList () with:

const interval = setInterval(loadList, 60000); // Adjust interval as desired
return () => clearInterval(interval)

Make sure the cache control headers set in the response to /getlist don't stop the browser from noticing updates.

Server push

Rip out your current code to get the data and replace it with something using websockets, possibly via Socket.IO. (There are plenty of tutorials for using Socket.io with React that can be found with Google, but its rather too involved to be part of a SO answer).

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

Comments

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.