Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.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 即使提供了第二个参数,useEffect钩子也在运行无限循环_Reactjs - Fatal编程技术网

Reactjs 即使提供了第二个参数,useEffect钩子也在运行无限循环

Reactjs 即使提供了第二个参数,useEffect钩子也在运行无限循环,reactjs,Reactjs,我可以发现类似的问题被问了几十次,但提供的解决方案对我来说并不适用。我有一个useffecthook,它运行一个函数从数据库返回一些数据 const VenueDetails = ({ venue_details, fetchVenueDetails, id }) => { React.useEffect(() => { fetchVenueDetails(id); }, [venue_details]); return (<div></div&

我可以发现类似的问题被问了几十次,但提供的解决方案对我来说并不适用。我有一个
useffect
hook,它运行一个函数从数据库返回一些数据

const VenueDetails = ({ venue_details, fetchVenueDetails, id }) => {

  React.useEffect(() => {
    fetchVenueDetails(id);
  }, [venue_details]);

return (<div></div>)
}
但这些解决方案对我不起作用。我肯定我遗漏了一些明显的东西,但如果有人能为我指出这一点,那就太好了

我也试过了

  React.useEffect(() => {
    fetchVenueDetails(id);
  }, [id]);

编辑:添加更多信息

此外,我的
fetchVenueDetails
函数位于
contextProvider

  fetchVenueDetails = (venue_id) => {
    this.setState({ loading: true });

    fetch(`/venues/details?venue_id=${venue_id}`)
      .then((res) => res.json())
      .then((data) => {
        this.setState({ loading: false });
        const details = data;
        this.setState({
          venue_details: details,
        });
      })
      .catch((error) => {
        console.log('error fetching venue details', error);
        this.setState({ loading: false });
      });
  };

发生无限循环是因为您在contextProvider组件中设置了状态

当您
setState
时,它会重新呈现您的contextProvider,api调用会一次又一次地发生

解决方案
与其直接更新您的
状态
,不如
调度
一个操作,并将
加载设置为true或false。
useffect
中添加此依赖项将有助于仅当
加载
reducer
操作更改时才重新呈现

除非您的
加载
状态通过
reducer
操作更改,否则您的
useffect
依赖关系不会更改,因此您的组件不会无限呈现

您不应该在功能组件中使用
state
setState

试试这个:

上下文提供程序组件

根据您的应用程序调整代码。
这里上下文提供程序和reducer位于它们自己的目录中,所以将reducer导入更改为reducer组件

我希望这对你有用,因为它对我有用


快乐编程:)

似乎
id
应该在依赖项数组中?同意@Nick-依赖项数组应该只包含那些可能在使用效果中发生变化的项<代码>id
可能就是您想要的。当您执行提取时,地点\u详细信息可能正在更改,这正是触发useEffect再次运行的原因。我刚刚更新了我的问题。@tdammon这是因为您不能在arrow函数中使用
this.setState()
。我甚至没有看到您呈现任何内容或使用从
fetchVenueDetails()
检索到的任何数据。当然,任何包含一个值的JS标识符都可以用作react钩子依赖项,该值不能保证是稳定的引用。我刚刚意识到你提到过,即使有一个空的依赖数组,无限循环仍然在发生。。。听起来组件正在重新安装,而不是简单地重新招标。您能否提供一个示例,说明如何呈现
VenueDetails
组件?当
useReducer
状态更新时,是否会出现重新呈现上下文提供程序的问题?分派更新状态的操作仍会更新状态。此外,reducer函数应该简单地合并状态更新,在reducer中的
切换\u加载
操作将清除
场馆\u细节
状态。不,我有两周前的相同情况,我尝试了此代码,它对我有效。infinte渲染问题已解决。我必须在减速机中添加…状态,我忘记了。谢谢:)@DrewReese不重新加载,因为加载状态仍然相同,并且仅当reducer更改它时才进行更改,无论contextProvider渲染多少次。而且
useffect
只有在加载状态发生变化时才会运行。哦,我明白了,所以您的建议是将
load
作为一个道具传递给
VenueDetails
,并用作调用
fetchVenueDetails
的依赖项和条件保护。您的解决方案/建议似乎暗示仅使用
useReducer
hook就可以解决状态更新/渲染循环问题。你可能想让你的答案中的这一部分更加公开和清晰。
  React.useEffect(() => {
    fetchVenueDetails(id);
  }, [venue_details, id]);
  fetchVenueDetails = (venue_id) => {
    this.setState({ loading: true });

    fetch(`/venues/details?venue_id=${venue_id}`)
      .then((res) => res.json())
      .then((data) => {
        this.setState({ loading: false });
        const details = data;
        this.setState({
          venue_details: details,
        });
      })
      .catch((error) => {
        console.log('error fetching venue details', error);
        this.setState({ loading: false });
      });
  };
import React, { createContext, useReducer, useEffect } from 'react';
import { venueReducer } from '../reducers/venueReducer';

export const venueContext = createContext();

const venueContextProvider = (props) => {
  const [venueDetails, venueDispatch] = useReducer(venueReducer, {
    venue_details: null,
    loading: true
  });

  fetchVenueDetails = (venue_id) => {
    venueDispatch({type: 'TOGGLE_LOADING'}):

    fetch(`/venues/details?venue_id=${venue_id}`)
      .then((res) => res.json())
      .then((data) => {
        venueDispatch({type: 'TOGGLE_LOADING'}):
        const details = data;
        venueDispatch({type: 'FETCH_DETAILS', payload: details});
      })
      .catch((error) => {
        console.log('error fetching venue details', error);
        venueDispatch({type: 'TOGGLE_LOADING'}):
      });
  };

  useEffect(() => {
    fetchVenueDetails(id);
  }, [venueDetails.loading]);

  return (
    <venueContext.Provider value={{ venueDetails, venueDispatch }}>
      {props.children}
    </venueContext.Provider>
  )
}

export default venueContextProvider;
export const venueReducer = (state, action) => {
  switch(action.type) {
    case 'FETCH_DETAILS':
      return {
        ...state,
        venue_details: action.payload
      }
    case 'TOGGLE_LOADING':
      return {
        ...state,
        loading: !state.loading
      }
  }
}