繁体   English   中英

使用自动完成功能获取 API 数据和过滤搜索输入

[英]Fetch API data with react and filter search input with autocomplete

我有一个关于 React 过滤器搜索输入的问题。

我现在有两个组件。

FirstPageComponent.js

import React from "react"
import AutoComplete from "./AutoComplete"

export class FirstPageComponent extends React.Component {
  constructor() {
    super()
    this.state = {
      rows: [],
      loading: true,
    }
  }
  async componentDidMount(searchTerm = "marvel") {
    await fetch(
      "https://api.themoviedb.org/3/search/movie?api_key=&query=" +
        searchTerm
    )
      .then(response => response.json())
      .then(responseData => {
        this.setState({
          rows: responseData.results,
          loading: false,
        })
      })
      .catch(error => {
        console.log("Error fetching and parsing data", error)
      })
  }
  render() {
    console.log(this.state.rows)
    return <AutoComplete movies={["hej"]} />
  }
}

自动完成.js

import React from "react"

export default class AutoComplete extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      rows: [],
      loading: false,
      userInput: "",
    }
  }

  onChange = e => {
    const { movies } = this.props
    const userInput = e.currentTarget.value

    const rows = movies.filter(
      suggestion =>
        suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
    )

    this.setState({
      rows,
      loading: true,
      userInput: e.currentTarget.value,
    })
  }

  onClick = e => {
    this.setState({
      rows: [],
      loading: false,
      userInput: e.currentTarget.innerText,
    })
  }

  render() {
    const {
      onChange,
      onClick,
      state: { rows, loading, userInput },
    } = this
    let moviesListComponent
    if (loading && userInput) {
      if (rows.length) {
        moviesListComponent = (
          <ul>
            {rows.map((movie, index) => {
              return (
                <li key={index} onClick={onClick}>
                  {movie}
                </li>
              )
            })}
          </ul>
        )
      } else {
        moviesListComponent = (
          <>
            <p>Couldn't find any movies. Try searching for another movie.</p>
          </>
        )
      }
    }

    return (
      <React.Fragment>
        <input type="search" onChange={onChange} value={userInput} />
        {moviesListComponent}
      </React.Fragment>
    )
  }
}
  • 我基本上想知道我是否以正确的方式接近这个。 我想从 fetch(” https://themovie.db ”) API 动态请求电影标题。

  • 如果用户输入类似于电影标题道具,则将电影标题作为道具发送,然后过滤自动完成组件中的值。

我是否以正确的方式思考这个问题? 我试图在与 AutoComplete 相同的组件中进行 fetch 调用,但没有让它按我想要的方式工作。 例如,如果您要解决此问题,您将如何设置组件结构?

随意询问是否有任何混淆。

谢谢

这些是我对上述代码的假设,如果有任何不正确,请告诉我。

  • 您正在执行初始 API 请求,以按搜索词列出电影列表。 该搜索词是在上面的代码之外给出的,并且不会被上面的任何机制改变。
  • 您将通过AutoComplete组件动态过滤 API 请求返回的数据。

这里的大部分 React 代码看起来都不错,但我有一些建议:

  1. 一般来说,我发现最好将事物列表完全分开,因此我将创建一个单独的MovieList function 组件,它只需要一个movie对象数组和一个titleFilter字符串并呈现它们。
  2. componentDidMount不采用 arguments。 searchTerm应该是FirstPageComponent的一个 prop(可能是由父组件通过某种选择或用户输入设置的)
  3. 我会将AutoComplete重命名为TitleFilter等。 它并不是真正的自动完成,它更像是一个过滤器字段。
  4. 这一行: if (loading && userInput) {将导致当用户尚未在过滤器字段中填写文本时不显示电影。 我不确定那是你想要的。
  5. 这行有点误导: <p>Couldn't find any movies. Try searching for another movie.</p> <p>Couldn't find any movies. Try searching for another movie.</p>因为您可能已经过滤掉了所有返回的结果。 在这种情况下,不是你找不到电影,而是你的过滤器限制太多。
  6. 对于onClick处理程序,我不确定这种通用方法是否最好。 例如,如果您以某种方式单击<ul> ,它可能会产生奇怪的交互。 为了改善这一点,我建议每个电影行组件实现自己的onClick并调用 function 来设置过滤器。
  7. 我敢打赌,您将不得不处理分页。 检查您的 API 并查看它为此做了什么,并确保您正在考虑它。

小尼特:

  1. userInput: e.currentTarget.value,可以缩写为userInput, ,它是userInput: userInput,的简写(你已经有一个名为userInput的变量。)
  2. 对于key道具,实际的唯一 id 会更好,以防您更改过滤并且索引号不再与您正在呈现的唯一行对齐。
  3. 我喜欢提前 go 并为每一行创建一个单独的组件,所以我会制作一个MovieRow function 组件,它需要一个movie object 并渲染它。 它只是使代码更简洁。 (并使上面的#6更容易实现)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM