Reactjs React Hooks-Ref在useEffect中不可用
我在用钩子。我正在尝试访问Reactjs React Hooks-Ref在useEffect中不可用,reactjs,react-hooks,Reactjs,React Hooks,我在用钩子。我正在尝试访问useffect函数中User组件的ref。但是我得到的elRef.current值为null,尽管我将elRef.current作为第二个参数传递给useffect。但是我想得到对div元素的引用。但在useffect的外部(函数体),ref值可用。为什么呢?如何获取useffect中的elRef.current值 代码 import React, { Component, useState, useRef, useEffect } from "react"; co
useffect
函数中User
组件的ref
。但是我得到的elRef.current
值为null
,尽管我将elRef.current
作为第二个参数传递给useffect
。但是我想得到对div
元素的引用。但在useffect
的外部(函数体),ref
值可用。为什么呢?如何获取useffect
中的elRef.current
值
代码
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;
import React,{Component,useState,useRef,useffect}来自“React”;
const useFetch=url=>{
const[data,setData]=useState(null);
const[isLoading,setIsLoading]=useState(false);
const[error,setError]=useState(null);
使用效果(
() => {
设置加载(真);
获取(url)
。然后(响应=>{
如果(!response.ok)抛出错误(response.statusText);
返回response.json();
})
。然后(json=>{
设置加载(假);
setData(json.data);
})
.catch(错误=>{
设置加载(假);
设置错误(错误);
});
},
[网址]
);
返回{data,isLoading,error};
};
常量用户=({id})=>{
const elRef=useRef(null);
const{data:user}=useFetch(`https://reqres.in/api/users/${id}`);
useffect(()=>{
控制台日志(“参考”,参考当前);
},[elRef.current]);
如果(!user)返回null;
返回{user.first\u name+“”+user.last\u name};
};
类应用程序扩展组件{
状态={
用户ID:1
};
handleNextClick=()=>{
this.setState(prevState=>({
userId:prevState.userId+1
}));
};
handlePrevNext=()=>{
this.setState(prevState=>({
userId:prevState.userId-1
}));
};
render(){
返回(
this.handlePrevClick()}
已禁用={this.state.userId===1}
>
普雷沃
this.handleNextClick()}>Next
);
}
}
导出默认应用程序;
谢谢 这是一种可预测的行为 正如前面提到的
@estus
您面临这个问题,因为第一次在componentDidMount
上调用它时,您会得到null
(初始值),并且get只在下一次elRef
中更新一次,因为实际上,引用仍然是相同的
如果需要对每次用户更改进行反思,则应将[user]
作为第二个参数传递给函数,以确保在用户更改时激发useffect
是更新的沙盒
希望有帮助 useEffect同时用作componentDidMount和componentDidUpdate, 在安装组件时,您添加了一个条件:
if (!user) return null;
return <div ref={elRef}>{user.first_name + " " + user.last_name}</div>;
如果(!user)返回null;
返回{user.first\u name+“”+user.last\u name};
由于装载时的上述条件,您没有用户,因此它返回null,并且在添加ref的DOM中没有装载div,因此在useffect中,由于没有呈现elRef的当前值,因此无法获得elRef的当前值
当div装入dom时,单击next,您将获得elRef.current的值。这里的假设是
useEffect
需要检测对ref.current
的更改,因此需要在依赖项列表中包含ref
或ref.current
。我认为这是因为es lint
有点过于迂腐
实际上,useffect
的全部要点是,它保证在渲染完成并且DOM准备就绪之前不会运行。这就是它处理副作用的方式
因此,在执行useffect
时,我们可以确保设置了elRef.current
代码的问题在于,在填充用户
之前,您不会使用
运行渲染器。因此,要引用的DOM节点elRef
尚不存在。这就是为什么会出现null
日志记录-与依赖项无关
顺便说一句:一种可能的替代方法是在效果挂钩内填充div:
useffect(
() => {
如果(!user)返回;
elRef.current.innerHTML=`${user.first\u name}${user.last\u name}`;
},[用户]
);
这样,
if(!user)返回null用户组件中的代码>行是不必要的。删除它,并且elRef.current
保证从一开始就用div节点填充。您应该使用useCallback而不是reactjs中建议的useRef
React将在ref连接到其他节点时调用该回调
替换此项:
const elRef = useRef(null);
useEffect(() => {
console.log("ref", elRef.current);
}, [elRef.current]);
为此:
const elRef = useCallback(node => {
if (node !== null) {
console.log("ref", node); // node = elRef.current
}
}, []);
我们可以在初始呈现中看到用户名(在获取解析后)。这意味着用户在场<代码>下一步
按钮,用于获取下一个用户。@REDDYPRASAD,不,它在初始渲染时不存在,请尝试删除该条件,您的代码将崩溃。这意味着它最初不会呈现该div。@REDDYPRASAD,如果删除该条件,它将显示“无法读取null的属性'first_name'”error@REDDYPRASAD,您可以执行{!user?“”:user.first\u name+“”+user.last\u name},并删除用户检查的条件。由于我们不需要单击“下一步”按钮来获取用户,因此被否决。如果是这种情况,则在页面加载时如何查看用户名(不单击“下一步”)我以为在render方法已经运行之后调用了useffect
?我不明白为什么它应该为null。@jayarjo是的,你是对的。在第一次渲染时,在从服务器获取之前没有用户,所以这就是为什么我们会得到这样的结果。如果没有用户,则存在呈现null
的条件,因此ref初始化时仍然是null
。对。我错过了他实际返回null
他自己的那一行。