facebookexperimental/Recoil

waitForAll does not prevent component re-renders while it is waiting

Open

#1,698 opened on Mar 28, 2022

View on GitHub
 (1 comment) (3 reactions) (0 assignees)JavaScript (1,151 forks)batch import
help wantedperformance

Repository metrics

Stars
 (19,428 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

Example taken from the documentation

https://recoiljs.org/docs/guides/asynchronous-data-queries#concurrent-requests

const currentUserIDState = atom({
  key: 'CurrentUserID',
  default: null,
});

const userInfoQuery = selectorFamily({
  key: 'UserInfoQuery',
  get: userID => async () => {
    const response = await myDBQuery({userID});
    if (response.error) {
      throw response.error;
    }
    return response;
  },
});

const currentUserInfoQuery = selector({
  key: 'CurrentUserInfoQuery',
  get: ({get}) => get(userInfoQuery(get(currentUserIDState))),
});

const friendsInfoQuery = selector({
  key: 'FriendsInfoQuery',
  get: ({get}) => {
    const {friendList} = get(currentUserInfoQuery);
    const friends = get(waitForAll(
      friendList.map(friendID => userInfoQuery(friendID))
    ));
    return friends;
  },
});

With this design, a component with useRecoilValue(friendsInfoQuery) is re-rendered every time that await myDBQuery({userID}) is resolved.

My expectation is get(waitForAll) would wait for all of these await statements to complete before triggering a component render with the final result, in a similar manner to this pattern:

const [friendsList, setFriendsList] = useState([]);

Promise.all(getFriendQueries).then((result) => {
  setFriendsList(result);
});

Contributor guide