私はReactHooksを使用しています。 ref
関数のUser
コンポーネントのuseEffect
にアクセスしようとしています。しかし、私はelRef.current
値としてnull
を使用しましたが、elRef.current
の2番目の引数として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;
よろしくお願いします!
ここでの前提は、useEffect
が_ref.current
_への変更を検出する必要があるため、依存関係リストにref
または_ref.current
_を含める必要があるということです。これは、_es-lint
_が少し過大評価されているためだと思います。
実際、useEffect
の要点は、レンダリングが完了してDOMの準備ができるまで実行されないことを保証することです。それはそれが副作用を処理する方法です。
したがって、useEffect
が実行されるまでに、_elRef.current
_が設定されていることを確認できます。
コードの問題は、user
が入力されるまで、_<div ref={elRef}...>
_でレンダラーを実行しないことです。したがって、elRef
が参照するDOMノードはまだ存在しません。これがnull
ロギングを取得する理由です-依存関係とは何の関係もありません。
ところで、考えられる代替策の1つは、エフェクトフック内にdivを設定することです。
_useEffect(
() => {
if(!user) return;
elRef.current.innerHTML = `${user.first_name} ${user.last_name}`;
}, [user]
);
_
そうすれば、Userコンポーネントのif (!user) return null;
行は不要になります。それを削除すると、_elRef.current
_には最初からdivノードが入力されることが保証されます。