所以我有这样的代码:
useEffect(async () => {
if (someData) {
try {
console.log('inside try block', someData) // undefined
const response = await get(apiUrl('urlInObject') + `${someData}`, {
someData,
})
const { returnedData: someData, someOtherReturnedData } = response
setDataInSessionStore({
someData,
someOtherReturnedData,
})
showNotification({
type: 'success',
message: `The operation was successful.`,
})
router.push('/pages/other-page')
} catch (error) {
if (error.code === 400) {
showNotification({ message: `${error.data}` })
}
if (error.code === 404) {
showNotification({
message: `'${someData}' is not valid. Please try again.`,
})
router.push('/pages/different-page')
}
console.error('ERROR: ', error)
}
}, [])
从store.js导入的setDataInSessionStore的源,使用带有persistent:的zustand
import create from 'zustand'
import { devtools, persist } from 'zustand/middleware'
// items in here don't expire on hard refresh
export const useSession = create(
devtools(
persist(
(set, get) => ({
dataInSessionStore: {},
setDataInSessionStore: (dataInSessionStore) => set({ dataInSessionStore }),
}),
{
name: 'my-session', // unique name
getStorage: () => sessionStorage,
}
)
)
)
showNotification组件内部:
import React from 'react'
let ref
export function showNotification (notification) {
ref && ref.setState({ ...ref.state, ...notification, open: true })
}
export class Notification extends React.Component {
constructor (props) {
super(props)
this.state = { open: false, message: null, type: 'error', length: 3000 }
}
componentDidUpdate () {
if (this.state.message) {
this.timeout && clearTimeout(this.timeout)
this.timeout = setTimeout(
() => this.timeout && this.setState({ open: false }),
this.state.length
)
}
}
componentWillUnmount () {
this.timeout && clearTimeout(this.timeout)
}
render () {
const { open, message, type } = this.state
if (!ref) ref = this
if (!message) return null
return (
<div className={`notification-bar ${type} ${open ? 'bar-open' : 'bar-closed'}`}>
<span className='text'>
{message}
</span>
<div className='close-icon' />
</div>
)
}
}
export default Notification
下面是使用Promises的代码示例:
useEffect(() => {
if (someData) {
setLoading(true)
get(apiUrl('someUrl') + `${someData}`, {
someData,
})
.then((response) => {
const { data: someData, someOtherData } = response
setDataInSessionStore({
someData,
someOtherData,
})
showNotification({
type: 'success',
message: `The operation was successful.`,
})
router.push('/pages/other-page')
})
.catch((error) => {
if (error.code === 400) {
showNotification({ message: `${error.data}` })
}
if (error.code === 404) {
showNotification({
message: `'${someData}' is not valid. Please try again.`,
})
router.push('/pages/different-page')
}
console.error('ERROR: ', error)
})
}
}, [])
我记录了try块外的数据,数据存在,但try块内的数据未定义。如果我将代码切换为使用Promises而不是异步等待+尝试捕获,则数据存在。我正在使用NextJS,并使用带有persistent的zustand存储来将数据设置到会话存储。
您应该将someData
附加到useEffect
的第二个参数的数组中,因为someData
是局部状态之一,您的副作用取决于someData
。
这是我创建的CSB。
useEffect(() => {
const someFunction = async () => {
if (!someData) return
try {
console.log(someData) // someData is undefined
// make an API request with the data and do something
} catch (error) {
console.error('ERROR: ', error)
}
}
someFunction()
}, [someData])
您是想在该组件中查询动态页面的数据,还是想查询带有最终在动态页面中呈现的道具的JSX.Element(如[slug].js(?
如果上面的情况是真的,那么你只需要在router.query
的末尾加上方括号内调用的动态页面
例如,对于文件pages/services/[slug].tsx
,我调用以下内容:
const router = useRouter();
const slug = router.query.slug as string;
你可能想知道为什么我在router.query.slug
之后断言as string
;这样做的原因是因为CCD_ 9解析为CCD_。由于它不是一个包罗万象的路由,所以我只想要一个解析的slug字符串值。
也就是说,router.query
本身是具有以下类型定义的ParsedUrlQuery
类型:
interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> {}
您可能想知道有条件未定义的值来自哪里,因为到目前为止,它在这些定义中都不明显。NodeJS.Dict
中的字典是条件未定义的根所在的位置:
interface Dict<T> {
[key: string]: T | undefined;
}
这就是你在试块中获得undefined
的最终方式
为了对其进行分解,node_modules/next/dist/next-server/lib/router/router.d.ts
中有一个名为interpolateAs
的函数,其定义如下:
export declare function interpolateAs(route: string, asPathname: string, query: ParsedUrlQuery): {
params: string[];
result: string;
};
它正在为route
查找[name].js或[name].tsx;必须将此名称附加到已解析的url查询(router.query.name(中,才能正确解析数据。