开发者问题收集

未捕获的类型错误:无法读取 ReactJS 中为 null 的属性“value”

2022-03-02
2227

我正在尝试在React中创建一个通过TMDB API进行搜索的搜索栏,但我遇到了一些问题。每当我输入搜索栏时,我都会出现一个错误,说 无法读取null的属性(读取'value') ,我不确定问题可能是什么以及为什么它以null为单位。我在

941614447

中调用提及。

3个回答

您可以尝试使用 可选链接 ( ?. )

function Search() {
  const [searchQuery, setSearchQuery] = useState(""); 
  const [timeoutId, updateTimeoutId] = useState();

  const fetchData = async (searchString) => {
    const response = await axios.get(`https://api.themoviedb.org/3/search/movie?api_key=f134dfeac1ebb17feefa58d7f94e94cd&language=en-US&query=${searchString}&page=1&include_adult=false`);
    console.log(response);
  };

  const onTextChange = (e) => {
    clearTimeout(timeoutId);
    setSearchQuery(e.target?.value);
    const timeout = setTimeout(() => fetchData(e.target?.value), 500);
    updateTimeoutId(timeout);
  };

  return(
    <div> 
      <SearchBox>
      <SearchInput placeholder="SEARCH" value={searchQuery} onChange={onTextChange}></SearchInput>
      </SearchBox></div>
  );
}
Zach Jensz
2022-03-02

e.target.value 在 Web API 超时返回后不再存在。该函数已结束执行, e 参数将不再存在。

相反,请在 setTimeout 回调函数中尝试使用 useRef 而不是 e.target.value ,这样当它返回时,它可以引用最新的更改。

类似这样:

function Search() {
  const [searchQuery, setSearchQuery] = useState("");
  const [timeoutId, updateTimeoutId] = useState();

  const query = useRef(searchQuery);

  const fetchData = async (searchString) => {
    const response = await axios.get(`https://api.themoviedb.org/3/search/movie?api_key=f134dfeac1ebb17feefa58d7f94e94cd&language=en-US&query=${searchString}&page=1&include_adult=false`);
    console.log(response);
  };

  const onTextChange = (e) => {
    clearTimeout(timeoutId);
    setSearchQuery(e.target.value);
    query.current = e.target.value;
    const timeout = setTimeout(() => fetchData(query.current), 500);
    updateTimeoutId(timeout);
  };

  return(
    <div> 
      <SearchBox>
      <SearchInput placeholder="SEARCH" value={searchQuery} onChange={onTextChange}></SearchInput>
      </SearchBox></div>
  );
PsiKai
2022-03-02

再次查看您的代码后,我怀疑这是超时回调中的第二次事件访问,此后该事件访问已被取消。您应该在回调范围内保存对事件值的引用,这样就不会对事件对象产生持久的依赖。

const onTextChange = (e) => {
  const { value } = e.target;

  clearTimeout(timeoutId);

  setSearchQuery(value);
  const timeout = setTimeout(() => fetchData(value), 500);
  updateTimeoutId(timeout);
};

另外,仅供参考,除非您需要 timeoutId 作为状态的一部分来触发重新渲染或其他操作,否则更常见的是在此处使用 React ref 来存储对计时器 ID 的引用。据我所知,您只是在限制 fetchData 调用,无需触发不必要的渲染。

示例:

const timeoutIdRef = useRef();

useEffect(() => {
  // clear any running timeouts upon component unmount
  return () => clearTimeout(timeoutIdRef.current);
}, []);

...

const onTextChange = (e) => {
  const { value } = e.target;

  clearTimeout(timeoutIdRef.current);

  setSearchQuery(value);
  timeoutIdRef.current = setTimeout(() => fetchData(value), 500);
};
Drew Reese
2022-03-02