React Hook useEffect 缺少依赖项:“context”。要么包含它,要么删除依赖数组

问题描述 投票:0回答:1

我的目标是当用户在输入中键入内容时发出 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个回答
2
投票

React
文档这里提到了关于无限循环的完全相同的事情。因此,无限循环的原因是,在上下文渲染函数中,您在每次调用渲染时都会创建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. 消费者调用上下文进行另一个搜索查询,我们就陷入了无限循环!
  5. 解决方案是保留同一对象的上下文值,而仅更新其属性。这可以通过将所有必要的属性放入上下文状态中来完成。像这样:

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> ); } }

© www.soinside.com 2019 - 2024. All rights reserved.