React отображает только один элемент из списка, загруженного с firebase - PullRequest
0 голосов
/ 07 августа 2020

Я пытаюсь показать список пользователей, получаемый из базы данных Firebase Realtime. По журналам я их всех получаю! Но на экране появляется только первый. Если я поставлю в качестве зависимости users, я получаю бесконечное l oop в журналах, но все еще один элемент на экране. useCallback тоже не помогло. Если я заполню поля ввода на экране, тем самым запустив повторный рендеринг, я получу всех пользователей. Почему это не ставит их всех в первую очередь? Может быть, что-то с Typescript?

Спасибо!

...
const [users, setUsers] = useState<any[]>([]);
const [usersRef] = useState<any>(firebase.database().ref().child('users'));

...
const getUsers: () => void = useCallback(() => {
    const loadedUsers: any[] = []
    usersRef.on('child_added', (snap: any) => {
      loadedUsers.push(snap.val())
      setUsers(loadedUsers)
      console.log('loadedUsers', loadedUsers);
    })
  }, [setUsers, usersRef])

  useEffect(() => {
    getUsers();
    return () => usersRef.off()
  }, [usersRef, getUsers])


  const displayUsers = (users: any) => {
    console.log(users);
    return users.length > 0 && users.map((user: any) =>
      <li key={user.id}>
        {user.email}
      </li>
    )
  }
...

  <ul>
    {displayUsers(users)}
  </ul>

Итак, благодаря @Renaud Tarne c, это оказалась проблема со слушателем firebase. Пришлось слушать изменение value вместо child_added. Ниже новая версия. Не очень нравится, каким оказался displayUsers, но работает. Если у кого-то есть предложения, я был бы рад увидеть.

Еще раз спасибо!

  const getUsers: () => void = useCallback(() => {
    const loadedUsers: any[] = []
    usersRef.on('value', (snap: any) => {
      loadedUsers.push(snap.val())
      setUsers(loadedUsers)
      console.log('loadedUsers', loadedUsers);
    })
  }, [setUsers, usersRef])
...


const displayUsers = (users: any) => {
    console.log(users);
    return users.length > 0 && users.map((userObj: any) => {
      const users = []
      for (const key in userObj) {
        users.push(userObj[key])
      }
      return users.map((user: any) =>
        <li key={user.id}>
          {user.email}
        </li>
      )
    }
    )
  }

1 Ответ

1 голос
/ 07 августа 2020

Если я правильно понимаю вашу проблему, это потому, что вы используете событие child_added вместо value. Посмотрите разницу между ними в do c:

value event

Это событие запускается один раз с начальным данные, хранящиеся в этом месте, а затем запускаются снова при каждом изменении данных. DataSnapshot, переданный в обратный вызов, будет для местоположения, в котором был вызван on() ..

child_added событие

Это событие будет запускаться один раз для каждого начального дочернего элемента. в этом месте, и он будет запускаться снова каждый раз, когда добавляется новый дочерний элемент. DataSnapshot, переданный в обратный вызов, будет отражать данные для соответствующего дочернего элемента .

Таким образом, с событием value вы получаете все данные в этом месте, а с событие child_added вы получаете данные о ребенке.

...