Reactjs 使用useQuery和useEffect进行简单搜索
我有一个相当复杂的组件,现在我正在尝试实现一个搜索,用户可以在其中键入内容并过滤结果Reactjs 使用useQuery和useEffect进行简单搜索,reactjs,graphql,apollo,Reactjs,Graphql,Apollo,我有一个相当复杂的组件,现在我正在尝试实现一个搜索,用户可以在其中键入内容并过滤结果 // query const GET_ACCOUNTS = gql` query accounts{ accounts{ id name status company{ id name } } } `; 问题是,当我开始在搜索字段中键入内容时,我会查看我的搜索结果,当我键入一个字符时,它会
// query
const GET_ACCOUNTS = gql`
query accounts{
accounts{
id
name
status
company{
id
name
}
}
}
`;
问题是,当我开始在搜索字段中键入内容时,我会查看我的搜索结果
,当我键入一个字符时,它会被过滤,但当我键入下一个字符时,它会中断
TypeError: Cannot read property 'filter' of undefined
而且,即使我键入了一个字母,它也不会显示在视图中。根据您的数据,
搜索结果的初始值是一个带有帐户
键的字典。但是,当您在useffect
部分中更新它时,它将更改为一个列表:
useEffect(() => {
if (searchTerm) {
const results = searchResults.accounts.filter((c => c.name.toLowerCase().includes(searchTerm)))
// This changes the value of searchResults to an array
setSearchResults(results)
}
}, [searchTerm])
当在useffect
中调用setSearchResults
时,searchResults
的值将从一个对象更改为一个数组:
由此:
搜索结果={
账户:[
...
]
}
为此:
搜索结果=[
...
]
这就是为什么它会引发TypeError:在第一次搜索后无法读取未定义的
的属性“filter”,因为不再有帐户
键
要解决这个问题,您需要在搜索结果的数据类型上保持一致,最好首先将其列为一个列表。您可以在onCompleted
部分中执行此操作:
const { loading } = useQuery(GET_ACCOUNTS, {
fetchPolicy: "no-cache",
skip: userType !== 'OS_ADMIN',
onCompleted: (data) => setSearchResults(data.accounts || [])
});
请注意,我们将searchResults
设置为accounts
值。之后,您还需要了解如何访问搜索结果
{searchResults &&
searchResults.map(c => {
return (
...renderhere
)
})
}
您的useffect
将如下所示:
useEffect(() => {
if (searchTerm) {
const results = searchResults.filter((c => c.name.toLowerCase().includes(searchTerm)))
setSearchResults(results)
}
}, [searchTerm])
提示:
您可能需要将搜索结果
重命名为帐户
,以使其更清晰。还请注意,在第一次搜索之后,您的选项将仅限于以前的搜索结果,因此您可能还希望将所有帐户存储在不同的变量中:
const [allAccounts, setAllAccounts] = useState([])
const [searchedAccounts, setSearchedAccounts] = useState([])
// useQuery
const { loading } = useQuery(GET_ACCOUNTS, {
fetchPolicy: "no-cache",
skip: userType !== 'OS_ADMIN',
onCompleted: (data) => {
setAllAccounts(data.accounts || [])
setSearchedAccounts(data.accounts || [])
}
});
// useEffect
useEffect(() => {
if (searchTerm) {
// Notice we always search from allAccounts
const results = allAccounts.filter((c => c.name.toLowerCase().includes(searchTerm)))
setSearchedAccounts(results)
}
}, [searchTerm])
你能从get查询中给出searchResults
的初始值吗?@RieljunLiguid刚刚添加了一个示例,但是有不止一个,所以当我渲染输出时,我会做如下操作:{searchedAccounts.map(()=>{return}}
,如果是这样的话,如果searchedAccounts
中没有任何内容,如何使其映射到allAccounts
?这意味着我想在查询运行后提取完整的帐户列表,但当每个要筛选的字母都输入了搜索词时,我就开始筛选它,然后显示它们。如果搜索词中没有任何内容,则显示全部。希望这是有意义的。如果是这样的话,你可以从allAccounts
设置searchedAccounts
的值,类似这样:setSearchedAccounts(allAccounts)
好的,那么我将按照提示中的建议进行设置。因此,我是否需要修改useffect
来执行此操作?在我的渲染中,我正在使用searchedAccounts&&searchedAccounts.map
我尝试添加另一个useffect
但它不会更改渲染视图:useffect(()=>{if(searchedAccounts){setSearchedAccounts(searchedAccounts)},[searchedAccounts])
因此,包括所有账户
不起作用,但添加搜索账户
起作用了!非常感谢你的帮助!
useEffect(() => {
if (searchTerm) {
const results = searchResults.accounts.filter((c => c.name.toLowerCase().includes(searchTerm)))
// This changes the value of searchResults to an array
setSearchResults(results)
}
}, [searchTerm])
const { loading } = useQuery(GET_ACCOUNTS, {
fetchPolicy: "no-cache",
skip: userType !== 'OS_ADMIN',
onCompleted: (data) => setSearchResults(data.accounts || [])
});
{searchResults &&
searchResults.map(c => {
return (
...renderhere
)
})
}
useEffect(() => {
if (searchTerm) {
const results = searchResults.filter((c => c.name.toLowerCase().includes(searchTerm)))
setSearchResults(results)
}
}, [searchTerm])
const [allAccounts, setAllAccounts] = useState([])
const [searchedAccounts, setSearchedAccounts] = useState([])
// useQuery
const { loading } = useQuery(GET_ACCOUNTS, {
fetchPolicy: "no-cache",
skip: userType !== 'OS_ADMIN',
onCompleted: (data) => {
setAllAccounts(data.accounts || [])
setSearchedAccounts(data.accounts || [])
}
});
// useEffect
useEffect(() => {
if (searchTerm) {
// Notice we always search from allAccounts
const results = allAccounts.filter((c => c.name.toLowerCase().includes(searchTerm)))
setSearchedAccounts(results)
}
}, [searchTerm])