【问题标题】:React Hook useEffect has a missing dependency: 'context'. Either include it or remove the dependency arrayReact Hook useEffect 缺少依赖项:'context'。包括它或删除依赖数组
【发布时间】:2020-05-31 16:34:56
【问题描述】:

我的目标是在用户输入内容时发出 API 请求。我正在成功获取数据。但是,该组件重新渲染了两次并给了我这个警告。如果我包含“上下文”,我会得到一个无限循环。这是我的代码:

Component.js:


const SearchBox = () => {
  const [searchTerm, setSearchTerm] = useState("");
  const { handleSearch, searchResults } = useContext(MovieContext);

  console.log(searchResults);

  useEffect(() => {
    let timer;
    timer = setTimeout(() => {
      handleSearch(searchTerm);
    }, 500);

    return () => clearTimeout(timer);
  }, [searchTerm]);

  const renderResults = () => {
    if (searchResults.length > 0) {
      searchResults.map(result => {
        return (
          <div key={result.Title}>
            <img src={result.Poster} alt={result.Title} />;
          </div>
        );
      });
    }
    return;
  };

  return (
    <>
      <label>
        <b>Search</b>
      </label>
      <input
        className="input"
        value={searchTerm}
        onChange={e => setSearchTerm(e.target.value)}
      />
      <div className="dropdown is-active">
        <div className="dropdown-menu">
          <div className="dropdown-content results">{renderResults()}</div>
        </div>
      </div>
    </>
  );
};

在这个 context.searchResults 之上是未定义的,尽管我将初始值设置为一个空数组。我想知道是什么原因造成的。我究竟做错了什么?下面是我的上下文代码:

Context.js:

const Context = React.createContext("");

export class MovieStore extends Component {
  constructor(props) {
    super(props);
    this.state = {
      searchResults: [],
      handleSearch: this.handleSearch
    };
  }

  handleSearch = async term => {
    try {
      if (term !== "") {
        const response = await axios.get("http://www.omdbapi.com/", {
          params: {
            apikey: apikey,
            s: term
          }
        });
        this.setState({ searchResults: response.data.Search });
      }
    } catch (error) {
      console.log(error);
    }
  };

  render() {
    return (
      <Context.Provider value={this.state}>
        {this.props.children}
      </Context.Provider>
    );
  }
}

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    React 文档here 中提到了关于无限循环的完全相同的事情。所以无限循环的原因是,在上下文渲染函数中,你创建new每次渲染被调用。

      render() {
        return (
          <Context.Provider
            // ! value object creates every time render is called - it's bad
            value={{ ...this.state, handleSearch: this.handleSearch }}
          >
            {this.props.children}
          </Context.Provider>
        );
      }
    

    当上下文状态更新时,它会导致每个消费者重新呈现。所以,如果你把context放在useEffect的依赖数组中,最终会导致死循环,因为context的值总是不同的。以下是发生的事情:

    1. 上下文进行搜索查询。

    2. 使用新数据更新上下文状态,这会导致所有消费者重新呈现。

    3. 在上下文消费者useEffect 看到上下文值已经 已更新并调用 setTimeout 将调用另一个搜索 在 500 毫秒内进入上下文提供程序。

    4. 消费者调用上下文进行另一个搜索查询,我们得到了一个无限循环!

    解决方案是保持上下文值相同的对象,同时只更新其属性。这可以通过将所有必要的属性放在上下文状态中来完成。像这样:

    export class MovieStore extends Component {
      handleSearch = async term => {
        try {
          if (term !== "") {
            const response = await axios.get("http://www.omdbapi.com/", {
              params: {
                apikey: "15bfc1e3",
                s: term
              }
            });
            this.setState({ searchResults: response.data.Search });
          }
        } catch (error) {
          console.log(error);
        }
      };
    
      state = {
        searchResults: [],
        handleSearch: this.handleSearch // <~ put method directly to the state
      };
    
      render() {
        return (
          <Context.Provider value={this.state}> // <~ Just returning state here
            {this.props.children}
          </Context.Provider>
        );
      }
    }
    

    希望对你有帮助

    【讨论】:

    • 感谢您的回答。我通过将方法直接置于上下文状态来尝试您的解决方案。如果我在顶部声明状态,我会得到未定义的 handleSearch 函数。如果我把它放在函数下面,它似乎正在工作。但是我仍然陷入无限循环。
    • 您能否将问题中的代码替换为新代码,以便我评估其错误所在
    猜你喜欢
    • 2021-10-29
    • 2020-07-19
    • 1970-01-01
    • 2021-08-24
    • 2023-04-09
    • 1970-01-01
    • 2021-09-10
    • 2020-09-26
    • 2020-11-05
    相关资源
    最近更新 更多