React - использовать крючок эффекта - componentDidMount для использования эффекта - PullRequest
1 голос
/ 22 мая 2019

Я хотел бы преобразовать это в useEffect hook:

КОД

componentDidMount () {
   this.messagesRef.on('child_added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;
    this.setState({messages: this.state.messages.concat(message 
  )});
});

ОБНОВЛЕННЫЙ КОД

const MessageList = () => {
  const [messages, setMessage] = useState([]);
  const [usernames, setUsernames] = useState('');
  const [contents, setContents] = useState('');
  const [roomId, setRoomId] = useState('');

  const messagesRef = MessageList.props.firebase.database().ref('messages');

  useEffect(() => {
    messagesRef.on('child added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;

    const [messages, setMessages] = useState({messages: messages.concat(message)});
  });
 })
}

Прямо сейчас это дает мне useState cannot be used in a callback.

Как я могу решить это или преобразовать это правильно?

Ответы [ 2 ]

2 голосов
/ 22 мая 2019

Там есть пара вещей.Во-первых, чтобы исправить код, вы можете обновить useEffect следующим образом:

useEffect(() => {
    messagesRef.on('child added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;

    setMessages(messages.concat(message)); // See Note 1
}, []); // See Note 2

Примечание 1

Строка setMessages - это то, как вы обновляете свое состояние.useState немного отличается от "старого" setState в том смысле, что полностью заменит значение состояния.Реакция Документация говорит:

Это потому, что когда мы обновляем переменную состояния, мы заменяем ее значение.Это отличается от this.setState в классе, который объединяет обновленные поля в объект.

Примечание 2

React Hooks меняет способ создания приложений, и это ненастоящий «перевод» из старых жизненных циклов.

Пустые скобки ([]) в последней строке сделают ваш код «похожим» на componentDidMount, но, что самое важное, заставят ваш эффект работать толькооднажды.

Дэн Абрамов сказал (убрал часть оригинального текста):

Хотя вы можете использовать Effect (fn, []), это не точный эквивалент.В отличие от componentDidMount, он будет захватывать реквизиты и состояния.Так что даже внутри обратных вызовов вы увидите начальный реквизит и состояние.(...) Имейте в виду, что ментальная модель эффектов отличается от componentDidMount и других жизненных циклов, и попытка найти их точные эквиваленты может сбить вас с толку больше, чем помочь.Чтобы стать продуктивным, вам нужно «мыслить эффектами», и их ментальная модель ближе к реализации синхронизации, чем к реагированию на события жизненного цикла.

Полная статья об использованииEffect здесь .

1 голос
/ 22 мая 2019

Вы попытались объявить состояние снова вместо использования средства обновления состояния

useEffect(() => {
  messagesRef.on('child added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;
    // setMessages is the state updater for messages
    // instead of an object with messages: messagesArray
    // just save it as an array the name is already messages
    setMessages([...messages, message]);
  });
// useEffect takes an array as second argument with the dependencies
// of the effect, if one of the dependencies changes the effect will rerun
// provide an empty array if you want to run this effect only on mount
}, []);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...