首页 > 解决方案 > 在 Next.js 中访问查询值

问题描述

我正在开发 Next.js 应用程序并尝试创建无限滚动和搜索输入。

当用户到达页面底部时,无限滚动将再加载 6 个项目。搜索输入将过滤结果并仅返回标题中包含字符串输入的项目。

这两个功能单独工作都很好,问题在于将它们结合起来。

问题阶段是:

  1. 输入搜索输入 - 例如"a"
  2. 滚动到页面底部

预期:"a"打开搜索过滤器的更多结果。

实际: search是一个空字符串,因此结果上没有过滤器。

在调试scrollHandler函数时,searchprop 是一个空字符串,即使 URL 查询中存在搜索参数。

getServerSideProps

export async function getServerSideProps({ query }) {
  const search = query.search || '';
  const limit = query.limit || process.env.ITEMS
  const params = {
    limit,
    skip: process.env.Items_INIT_SKIP,
    orderBy: process.env.Items_INIT_ORDERBY,
    search
  };
  const { data: items } = await getItems(params)
  return { props: { items, search, limit } }
}

ItemsPage零件:

const ItemsPage = ({ items, search, limit }) => {
  const router = useRouter()
  useEffect(() => {
    window.addEventListener("scroll", handleScroll)
    return () => {
      window.removeEventListener("scroll", handleScroll)
    }
  }, [])

  const handleScroll = () => {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
      const newLimit = 6 + Number(limit);
      const path = search ? `${router.pathname}?search=${search}` : router.pathname
      const query = { ...router.query, limit: newLimit, search }
      router.push({
        pathname: router.pathname,
        query
      },
      path)
    }
  }

  const searchHandler = e => {
    const search = e.target.value

    router.push({
      pathname: router.pathname,
      query: {
        search
      },
    })
  }

  return (
    <div className={st(classes.root, {})}>
      <Input className={classes.Search} value={search} label='search' type='text' onChange={searchHandler} />
      <Items items={items} />
    </div>
  )
}

export default ItemsPage;

标签: javascriptreactjsnext.js

解决方案


将组件更改为class component,并使用 HOC:withRouter解决了问题,并允许访问查询参数和 props.

class ItemsPage extends React.Component {

    scrollHandler = () => {
        if (Math.ceil(window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
            const { router, limit, search } = this.props
            const newLimit = Number(limit) + Number(process.env.NEXT_PUBLIC_ITEMS_TO_ADD)
            const path = search ? `${router.pathname}?search=${search}` : router.pathname
            const query = { limit: newLimit, search }
            router.push({
                pathname: router.pathname,
                query
            },
                path)
        }
    }


    searchHandler = e => {
        const { router } = this.props
        const search = e.target.value
        const path = search ? `${router.pathname}?search=${search}` : router.pathname
            router.push({
                pathname: router.pathname,
                query: {
                    search
                },
            }, path)
    }

    componentDidMount() {
        window.addEventListener("scroll", this.scrollHandler)
    }

    componentWillUnmount() {
        window.removeEventListener("scroll", this.scrollHandler)
    }

    render() {
        const { Items, router } = this.props
        const { search } = router.query
        return (
            <div className={st(classes.root, {})}>
                <Input className={classes.Search} value={search} label='search' type='text' onChange={this.searchHandler} />
                <Items Items={Items} />
            </div>
        )
    }
}

export default withRouter(ItemsPage)

推荐阅读