【问题标题】:Accessing query values in Next.js在 Next.js 中访问查询值
【发布时间】:2021-01-17 18:40:08
【问题描述】:

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

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

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

问题阶段是:

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

预期:启用"a" 搜索过滤器会得到更多结果。

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

在调试 scrollHandler 函数时,search 属性是一个空字符串,即使 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;

【问题讨论】:

  • 来自getServerSideProps 的道具仅在初始页面渲染时加载。之后,它不会更新。试试const path = router.query?.search 看看是否可行。
  • 嘿@jdaz,抱歉耽搁了。我试过你的建议它仍然是空字符串。它不需要更新,搜索在url中的查询参数中,当页面渲染下一个时看不到它?目前我看到的唯一解决方案是从窗口对象中提取它,但感觉不对

标签: javascript reactjs next.js


【解决方案1】:

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

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)

【讨论】:

    猜你喜欢
    • 2020-08-17
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多