Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript NextJS-can';使用浅层路由器推送时,无法识别页面组件上发生状态更改的位置_Javascript_Reactjs_Next.js - Fatal编程技术网

Javascript NextJS-can';使用浅层路由器推送时,无法识别页面组件上发生状态更改的位置

Javascript NextJS-can';使用浅层路由器推送时,无法识别页面组件上发生状态更改的位置,javascript,reactjs,next.js,Javascript,Reactjs,Next.js,我有一个应用程序。它使用NextJS。我有一个页面,如下所示: import React from 'react' import { parseQuery } from '../lib/searchQuery' import Search from '../components/search' class SearchPage extends React.Component { static getInitialProps ({ query, ...rest }) { consol

我有一个应用程序。它使用NextJS。我有一个页面,如下所示:

import React from 'react'
import { parseQuery } from '../lib/searchQuery'
import Search from '../components/search'

class SearchPage extends React.Component {
  static getInitialProps ({ query, ...rest }) {
    console.log('GET INITIAL PROPS')
    const parsedQuery = parseQuery(query)
    return { parsedQuery }
  }

  constructor (props) {
    console.log('CONSTRUCTOR OF PAGE CALLED')
    super(props)
    this.state = props.parsedQuery
  }

  render () {
    return (
      <div>
        <div>
          <h1>Search Results</h1>
        </div>
        <div>
          <h1>DEBUG</h1>
          <h2>PROPS</h2>
          {JSON.stringify(this.props)}
          <h2>STATE</h2>
          {JSON.stringify(this.state)}
        </div>
        <div>
          <Search query={this.state} />
        </div>
      </div>
    )
  }
}

export default SearchPage
这里的意图是CSR接管-因此是浅层的
路由器.push
。页面URL发生更改,但不应再次触发
getInitialProps
,随后的查询更改将通过
componentWillUpdate
等进行处理。。我确认
getInitialProps
由于缺少相应的
console.log
触发,因此不会再次触发

问题 但是,在选中/取消选中
Search
组件上的select字段时,我惊讶地发现
SearchPage
的状态仍在更新,尽管没有证据表明调用了
this.setState()

constructor
没有被调用,
getInitialProps
也没有被调用,所以我不知道是什么导致状态发生变化

初始SSR后,调试块如下所示:

// PROPS
{
  "parsedQuery": {
    "manufacturer": [],
    "lowPrice": "",
    "highPrice": ""
  }
}
// STATE
{
  "manufacturer": [],
  "lowPrice": "",
  "highPrice": ""
}
然后在
搜索
中检查选择字段后,它会更新为:

// PROPS
{
  "parsedQuery": {
    "manufacturer": ["Apple"],
    "lowPrice": "",
    "highPrice": ""
  }
}
// STATE
{
  "manufacturer": ["Apple"],
  "lowPrice": "",
  "highPrice": ""
}
我找不到对这种行为的解释,没有任何输出到控制台,我也找不到如何通过开发工具跟踪状态更改的来源

当然,只有通过
componentdiddupdate
进行更新时,状态才应该更新?而且
parsedQuery
prop不应该只由
getInitialProps
更新吗?这就是创造和注入它的原因

为了进一步增加混淆,如果我更改
搜索
上的数字
输入
字段(例如
低价
),URL会按预期更新,但调试块中的道具或页面状态会发生更改。我无法理解这种不一致的行为

这是怎么回事

编辑


我增加了回购协议。它将这个问题复制到GitHub上的MWE上,您可以在这里克隆它:

哇,有趣的问题。这是一个有趣的小难题

TL;医生:这是你的错,但你是怎么做到的真的很微妙。首先,问题出在这一行:

在本例中,是这样的:

this.state = props.parsedQuery
让我们考虑一下那里到底发生了什么。

在IndexPage.getInitialProps中,您正在执行以下操作:`

const initialQuery = parseQuery({ ...query })
return { initialQuery }
通过Next的机制,这些数据将通过App.getInitialProps以pageProps.initialQuery的形式返回,然后在IndexPage中成为props.initialQuery,然后将其整体传递到搜索组件,搜索组件在其中“复制”对象以避免其变异。很好,对吗

你错过了什么

在lib/searchQuery.js中是这样一行:

searchQuery[field] = []
同一个数组正在向下传递到搜索中-除非您没有复制它。您正在复制props.query-它包含对该数组的引用

然后,在搜索组件中,更改复选框时执行以下操作:

const labelValue = this.state[label]

您正在修改在构造函数中“复制”的数组。你正在直接改变你的状态!这就是为什么initialQuery在主页上显示为更新-您对initialQuery引用的制造商数组进行了变异-它从未被复制。您拥有在getInitialProps中创建的原始引用

您应该知道的一件事是,即使在浅推时没有调用getInitialProps,应用程序组件仍然会重新呈现。它必须能够反映消耗组件的路线变化。在内存中对该数组进行变异时,重新渲染会反映更改。当您添加价格时,您没有改变initialQuery对象

解决这一切的办法很简单。在搜索组件构造函数中,需要查询的深度副本:

this.state = { ...cloneDeep(props.query) }
进行更改后,问题就会消失,您在打印输出中不再看到initialQuery的更改—正如您所期望的那样

您还需要更改此选项,即在您的状态下直接访问阵列:

const labelValue = this.state[label]
为此:

const labelValue = [...this.state[label]]
以便在更改阵列之前复制阵列。您可以通过立即调用setState来掩盖这个问题,但实际上您是在直接改变组件状态,这将导致各种奇怪的错误(如本例)

这是因为在组件状态中有一个全局数组发生了变异,所以所有这些变异都反映在不同的地方

const labelValue = [...this.state[label]]