【问题标题】:How to set data (array of objects) from get request in a state hook?如何在状态挂钩中从获取请求中设置数据(对象数组)?
【发布时间】:2020-11-14 05:10:29
【问题描述】:

您好,我在我的 App 组件中使用 axios 获取数据,然后在我的 SearchResults 组件的屏幕上显示它。

我目前发出我的 get 请求(在用户输入输入字段后 - 在另一个组件中)并使用 setSearchResults 将所有数据存储在我的状态 searchResults 中。然后我将数据作为道具传递给我的 SearchResults 组件,并通过它使用 & 映射,并根据一些逻辑在屏幕上显示正确的数据。

我想知道直接在我的异步函数中而不是在 SearchResults 组件中的函数中执行我的逻辑是否更有效。

我试图在异步函数中执行逻辑(可以在下面找到),但我的结果没有正确显示。当我在输入字段中输入内容时,它会检索与用户输入内容无关的数据。保持原样会更好吗?它不起作用的原因是因为我在状态挂钩中错误地设置了我的 get 请求中的数据吗?任何帮助表示赞赏,在此先感谢您!

function App() {
    const [keyword, setKeyword] = useState("")
    const [searchResults, setSearchResults] = useState([])

    const getAllData = async () => {
        return await getDataService(keyword)
            .then(({ data }) => {
                // currently I am just doing: 
                   setSearchResults(data.list)

                // my attempt below for doing the logic directly here 
                //instead of in showSearchResults() in my other component:
                return data.list.map((item) => {
                  if(item.searchterm.includes(keyword.toLowerCase())) {
                    setSearchResults([...searchResults, item])
                }
              })
            })
            .catch((err) => console.log(err))
    }

    return (
        <div className="App">
            <form className="container">
                <InputField keyword={keyword} setKeyword={setKeyword} getClothesData={getClothesData} />
                <SearchResults keyword={keyword} searchResults={searchResults} />
            </form>
        </div>
    );
}

const SearchResults = ({ keyword, searchResults }) => {
  const showSearchResults = () => {
    return searchResults.map((item, index) => {
      if (item.searchterm.includes(keyword.toLowerCase()) && keyword.length > 1) {
        return (
          <div className="text-bold" key={index}>
            <ul>
              <li className="input-fields search-results">
               {item.searchterm}
              </li>
            </ul>
          </div>
        );
      }
    });
  };
  return <div>{ keyword ? showSearchResults() : null }</div>;
}

【问题讨论】:

  • 首先你应该分开获取数据和过滤数据。获取数据应该在 useEffect 挂钩中。此外,您还可以分阶段快速解决问题。

标签: reactjs axios state


【解决方案1】:

看起来您尝试应用的逻辑不正确。

return data.list.map((item) => {
  if(item.searchterm.includes(keyword.toLowerCase())) {
    setSearchResults([...searchResults, item])
}

在这里,您正在映射列表中的项目,并一次又一次地设置searchResults 状态。 React 可能会使其成为批量更新,并且不会总是采用之前的状态值。

您可以通过在setSearchResults 中提供功能更新来避免这种情况发生

看看Why React useState with functional update form is needed?

【讨论】:

  • 所以你的意思是把它设置为:setSearchResults(searchReslts =&gt; [...searchResults, item])
  • @critical_maas 是的!另外,我希望您关注此处共享的其他答案。例如,Tarakumi 分享的答案
  • 我也关注了他的评论!谢谢。我尝试通过功能更新来提出建议,但我仍然得到不正确的结果。当我想要包含关键字的结果时,它会多次显示所有项目。
【解决方案2】:

在 useEffect 挂钩中发出您的服务器请求: 模板是这样的:

const App = () => {
  const [state, setState] = useState([])
  
  useEffect(() => {
    axios(url).then(({ data }) => setState(data))
  }, []) // empty array here means that hooks works once

}

【讨论】:

  • 谢谢!我对我的代码进行了此更改。欣赏它
  • 很高兴听到它有帮助!如果您发现有用的答案,您可以投票给他们 - 这会提高声誉,也让我很高兴!
猜你喜欢
  • 2020-07-31
  • 2021-02-11
  • 2021-03-16
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
相关资源
最近更新 更多