You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中SearchBox向Fetch URL传参报错:this.props.onSearchBox非函数

嘿,我来帮你搞定这个问题!你遇到的报错TypeError: this.props.onSearchBox is not a function是因为**SearchBox组件在App里渲染时没接收到onSearchBox这个回调props**,而且更深层的问题是你组件间的通信逻辑完全错了——不能把SearchBox组件直接塞进FetchMovie的请求URL里,组件是用来渲染UI的,不是传递数据的载体。咱们一步步来修复:

错误原因拆解

  1. 直接报错原因:你在App组件里写的是<SearchBox />,没有传递onSearchBox这个props,但SearchBox的handleSubmit里却尝试调用this.props.onSearchBox,自然会抛出“不是函数”的错误。
  2. 核心逻辑错误:FetchMovie里的fetch URL写法完全错误,<SearchBox onSearchBox={this.handleSubmit} />是JSX元素,不是字符串参数,不能直接拼进URL里。正确的做法是让父组件App作为中间层,管理搜索状态并传递给子组件。

具体修复步骤

步骤1:重构App组件,作为状态中间层

把App改成带状态的组件(用Hooks更简洁),用来存储用户输入的搜索关键词,同时给SearchBox传递回调,给FetchMovie传递搜索关键词:

import React, { useState } from 'react';
import './App.css';
import NavBar from './components/NavBar';
import SearchBox from './components/SearchBox';
import FetchMovie from './components/FetchMovie';

function App() {
  // 存储用户搜索的电影关键词
  const [searchKeyword, setSearchKeyword] = useState('');

  // 接收SearchBox传来的搜索值,更新状态
  const handleSearch = (keyword) => {
    setSearchKeyword(keyword);
  };

  return (
    <>
      <NavBar />
      {/* 给SearchBox传递onSearchBox回调 */}
      <SearchBox onSearchBox={handleSearch} />
      {/* 把搜索关键词传给FetchMovie */}
      <FetchMovie searchKeyword={searchKeyword} />
    </>
  );
}

export default App;

步骤2:修复SearchBox组件的小问题

去掉handleChange里多余的e.preventDefault()(input的onChange事件不需要阻止默认行为),同时增加空值判断避免无效搜索:

// SearchBox组件
import React, { Component } from 'react';
class SearchBox extends Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };
    // 你用了箭头函数定义方法,不需要在constructor里bind
  }
  handleChange = (e) => {
    // 移除多余的preventDefault
    this.setState({value: e.target.value});
  }
  handleSubmit = (e) => {
    e.preventDefault();
    let userInput = this.state.value.trim();
    if(userInput) { // 空值不触发搜索
      this.props.onSearchBox(userInput);
      console.log(`You searched for the movie ${userInput}`);
    }
  }
  render() {
    return (
      <div className="search-container">
        <form className="form-search" onSubmit={this.handleSubmit}>
          <input type="text" value={this.state.value} onChange={this.handleChange} placeholder="Search Movie Title..." />
        </form>
        <h5>{this.state.value}</h5>
      </div>
    );
  }
}
export default SearchBox;

步骤3:重构FetchMovie组件,实现按需搜索

原来的componentDidMount只会在组件挂载时请求一次,而且请求方法和URL写法都错了。我们改成当搜索关键词变化时发起请求,同时处理各种异常情况:

// FetchMovie组件
import React, { Component } from 'react';

class FetchMovie extends Component {
  constructor(props) {
    super(props);
    this.state = { error: null, isLoading: false, data: {} }; // 电影数据是对象,不是数组
  }

  // 抽离fetch请求方法
  fetchMovie = (keyword) => {
    this.setState({ isLoading: true });
    const API_KEY = 'dfbcc791';
    // 用encodeURIComponent处理关键词,避免特殊字符破坏URL
    const url = `http://www.omdbapi.com/?apikey=${API_KEY}&t=${encodeURIComponent(keyword)}`;
    
    // OMDb接口是GET请求,不是POST,之前的POST会导致请求失败
    fetch(url)
      .then(res => {
        if(!res.ok) throw new Error('网络请求失败');
        return res.json();
      })
      .then(movie => {
        // 处理OMDb返回的“未找到电影”错误
        if(movie.Error) {
          this.setState({ error: movie.Error, isLoading: false, data: {} });
        } else {
          this.setState({ isLoading: false, data: movie, error: null });
        }
      })
      .catch(error => {
        this.setState({ isLoading: false, error: error.message });
      });
  }

  // 当搜索关键词变化时,发起新请求
  componentDidUpdate(prevProps) {
    if(this.props.searchKeyword !== prevProps.searchKeyword && this.props.searchKeyword) {
      this.fetchMovie(this.props.searchKeyword);
    }
  }

  render() {
    const { error, isLoading, data } = this.state;
    
    if (error) {
      return <div>Error: {error}</div>;
    } else if (isLoading) {
      return <div>Loading...</div>;
    } else if(!Object.keys(data).length) {
      return <div>请输入电影名称进行搜索</div>;
    } else {
      return (
        <div className="display">
          <div className="column1">
            {/* 处理海报不存在的情况 */}
            <img src={data.Poster !== 'N/A' ? data.Poster : 'https://via.placeholder.com/300x450?text=No+Poster'} alt={`${data.Title} poster`} />
          </div>
          <div className="column2">
            <h3>Title: {data.Title}</h3>
            <h6>Actors: {data.Actors}</h6>
            <h6>Year: {data.Year}</h6>
            <h6>Runtime: {data.Runtime}</h6>
            <h6>Rated: {data.Rated}</h6>
            <p>Plot: {data.Plot}</p>
          </div>
        </div>
      );
    }
  }
}
export default FetchMovie;

关键修复点说明

  1. 修正了OMDb请求的方法:OMDb是GET请求,不是POST,之前的POST会导致请求失败;
  2. 增加了异常处理:包括网络错误、电影未找到的情况;
  3. 优化了数据逻辑:电影数据是对象不是数组,调整了state的初始值;
  4. 避免无效请求:只有当关键词变化且不为空时才发起请求;
  5. 处理了海报不存在的边界情况,避免页面出现破碎图片。

内容的提问来源于stack exchange,提问作者Chinonso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 09:47:37