React Hooks - ссылка недоступна внутри useEffect - PullRequest
0 голосов
/ 24 января 2019

Я использую ReactHooks. Я пытаюсь получить доступ к ref из User компонента в функции useEffect. Но я получаю elRef.current значение как null, хотя я передал elRef.current в качестве второго аргумента useEffect. Но я полагаю, чтобы получить ссылку на элемент div. Но снаружи (тело функции) значение useEffect, ref доступно. Это почему ? Как я могу получить значение elRef.current внутри useEffect?

код

import React, { Component, useState, useRef, useEffect } from "react";

const useFetch = url => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(
    () => {
      setIsLoading(true);
      fetch(url)
        .then(response => {
          if (!response.ok) throw Error(response.statusText);
          return response.json();
        })
        .then(json => {
          setIsLoading(false);
          setData(json.data);
        })
        .catch(error => {
          setIsLoading(false);
          setError(error);
        });
    },
    [url]
  );

  return { data, isLoading, error };
};

const User = ({ id }) => {
  const elRef = useRef(null);
  const { data: user } = useFetch(`https://reqres.in/api/users/${id}`);

  useEffect(() => {
    console.log("ref", elRef.current);
  }, [elRef.current]);
  if (!user) return null;
  return <div ref={elRef}>{user.first_name + " " + user.last_name}</div>;
};

class App extends Component {
  state = {
    userId: 1
  };

  handleNextClick = () => {
    this.setState(prevState => ({
      userId: prevState.userId + 1
    }));
  };

  handlePrevNext = () => {
    this.setState(prevState => ({
      userId: prevState.userId - 1
    }));
  };
  render() {
    return (
      <div>
        <button
          onClick={() => this.handlePrevClick()}
          disabled={this.state.userId === 1}
        >
          Prevoius
        </button>
        <button onClick={() => this.handleNextClick()}>Next</button>
        <User id={this.state.userId} />
      </div>
    );
  }
}

export default App;

Codesandbox link

Спасибо!

Ответы [ 3 ]

0 голосов
/ 24 января 2019

useEffect является заменой как componentDidMount, так и componentDidUpdate.Он вызывается при начальном рендеринге, когда ссылка имеет значение null.

. Если он вызывается только при последующих рендерах при изменении ссылки, он должен быть:

  useEffect(() => {
    if (!elRef.current)
      return;

    console.log("ref", elRef.current);
  }, [elRef.current]);
0 голосов
/ 24 января 2019

useEffect используется и как componentDidMount, и componentDidUpdate, во время монтирования компонента вы добавили условие:

if (!user) return null;
return <div ref={elRef}>{user.first_name + " " + user.last_name}</div>;

из-за вышеуказанного условия во время монтирования у вас нет пользователя, поэтому он возвращает null, а div не монтируется в DOM, в который вы добавляете ref, поэтому внутри useEffect вы не получаете текущее значение elRef, так как оно не отображается.

И при нажатии на следующий какdiv монтируется в dom, в котором вы получили значение elRef.current.

0 голосов
/ 24 января 2019

Это предсказуемое поведение.

Как уже упоминалось @estus вы сталкивались с этим, потому что в первый раз, когда он вызывается на componentDidMount, вы получаете null (начальное значение) и get обновляется только один раз при следующем elRef изменении, потому что на самом делессылка остается прежней.

Если вам необходимо отразить каждое изменение пользователя, вы должны передать [user] в качестве второго аргумента функции, чтобы убедиться, что useEffect срабатывает при изменении пользователя.

Здесь - обновленная песочница.

Надеюсь, это помогло.

...