javascript - setState 未更新子组件中的输入值

标签 javascript reactjs

在此应用程序中,我从 Unsplash API(具有 Express 后端、React 前端)获取图像。页面加载时,会出现一般图像(在 react-infinite-scroll-component 内呈现),如果您进行搜索,则会调用特殊的获取方法 (fetchSearchImages) 来获取新图像。无论哪种情况,它们都会在 react-infinite-scroll-component 实例中呈现。

我的问题是,提交包含搜索输入的表单后,搜索输入没有被清除。在输入中我有 value={props.inputValue} ,并且在父组件中,提交表单后 fetchSearchImages 被调用。在 fetchSearchImages 中,我尝试使用 this.setState() 重置输入值,但输入中显示的值保持不变。我还尝试在 handleSubmit() else block 中执行此操作,但也没有执行任何操作。

View live | GitHub repo

子搜索输入组件:

const SearchInput = props => {

  const onSubmit = e => {
    // Prevents GET request/page refresh on submit
    e.preventDefault();
    props.onFormSubmit();
  };

  return (
    <form onSubmit={onSubmit}>
      <div className="control">
        <input autoFocus value={props.inputValue} onChange={e => props.onSearch(e.target.value)} className="input" type="text" placeholder="Search" />
      </div>
    </form>
  );
}

父组件:

export class Images extends Component {
  state = {
    images: [],
    searchImages: [],
    count: 4,
    page: 1,
    searchPage: 1,
    term: '',
    search: false,
    newSearch: false,
    blankSearch: false,
    inputValue: ''
  };

  componentDidMount() {
    const { page, count } = this.state;
      axios
        .get(`/api/photos?page=${page}&count=${count}`)
        .then(res => this.setState({ images: res.data }));
    // To prevent same images being fetched upon scrolling (in the first call to fetchImages)
    this.setState({ page: page + count });
  }

  fetchImages = () => {
    const { page, count, images } = this.state;
    this.setState({ page: page + 1 });
    axios
      .get(`/api/photos?page=${page}&count=${count}`)
      .then(res =>
        this.setState({ images: images.concat(res.data) })
      );
  }

  fetchSearchImages = () => {
    const { searchPage, count, term, searchImages } = this.state;

    this.setState({ searchPage: searchPage + 1, inputValue: '' });

    axios
      .get(`/api/photos/search?term=${term}&page=${searchPage}&count=${count}`)
      .then(res =>
        this.setState({
          searchImages: searchImages.concat(res.data.results)
        })
      );
  }

  // Necessary to place fetchSearchImages in a setState callback to ensure other state is set first
  handleSubmit = () => {
    if (!this.state.inputValue) {
      this.setState({
        images: [],
        blankSearch: true,
        newSearch: false,
        search: false,
        searchImages: [],
        searchPage: 1,
        page: 1,
      }, this.fetchImages);
    } else {
      this.setState({
        term: this.state.inputValue,
        searchImages: [],
        searchPage: 1,
        page: 1,
        search: true,
        newSearch: true
      }, this.fetchSearchImages);
    }
  }

  handleInputChange = (e) => {
    this.setState({
      inputValue: e
    });
  }

  render() {
    return (
      <>

      <SearchInput onSearch={this.handleInputChange} value={this.state.inputValue} onFormSubmit={this.handleSubmit} />

      <div className="images">
        <InfiniteScroll
          dataLength={this.state.blankSearch ? this.state.images.length : (this.state.newSearch || this.state.search) ? this.state.searchImages.length : this.state.images.length}
          next={this.state.search ? this.fetchSearchImages : this.fetchImages}
          hasMore={true}
          loader={
            <div className="loader-dots">
              <span className="loader-dot"></span>
              <span className="loader-dot"></span>
              <span className="loader-dot"></span>
              <span className="loader-dot"></span>
            </div>
          }
        >
        {this.state.newSearch || this.state.search ? this.state.searchImages.map(image =>
          <Image key={image.id + Math.random()} image={image} />
        ) : this.state.blankSearch ? this.state.images.map(image =>
          <Image key={image.id + Math.random()} image={image} />
        ) : this.state.images.map(image =>
          <Image key={image.id + Math.random()} image={image} />
        )}
      </InfiniteScroll>
      </div>

      </>
    );
  }
}

最佳答案

您的输入似乎没有得到正确控制。

在您的 SearchInput 组件中,您引用了无效的 prop。您在父级中调用 prop value,但在子级中将其引用为 inputValue

将输入更改为:

<input autoFocus value={props.value} onChange={e => props.onSearch(e.target.value)} className="input" type="text" placeholder="Search" />

或者父级:

<SearchInput onSearch={this.handleInputChange} inputValue={this.state.inputValue} onFormSubmit={this.handleSubmit} />

关于javascript - setState 未更新子组件中的输入值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58963071/

相关文章:

angular - ViewChildren 和 ContentChildren QueryLists 监听什么样的变化?

javascript - 无法读取上下文提供程序中 useReducer Hook 更新的状态

javascript - 构建前"Target container is not a DOM element"

javascript - 使用 html2canvas 将 HTML 表格转换为 Canvas

javascript - Assets 管道 - application.js 未编译/加载

javascript - 在不设置默认值的情况下在 Backbone 模型上声明变量

reactjs - 使用 typescript 创建 React 应用程序 React 18

javascript - 查询 typescript 中的接口(interface)

php - 在网页中打开网页

javascript - 我怎么知道 React 组件已完成处理生命周期回调并准备好在我的测试中进行交互?