Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React Hooks-Ref在useEffect中不可用_Reactjs_React Hooks - Fatal编程技术网

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
他自己的那一行。