我有一个React服务器组件,它可以访问初始值,甚至可以将操作分派到redux存储中
初始值被设置为10
// store/counterSlice.ts
const initialState: CounterState = {
value: 10,
};
// app/serverComponent.tsx
export default async function ServerComponent() {
const data = await fetchSomeData();
store.dispatch(updateTestData(data)); // this works
const counter = store.getState().counter; // this works - gets the initial value of 10
console.log('this log is shown in the server');
return (
<main className={styles.main}>
<div className={styles.description}>
{/* shows the initial value of 10 */}
<p>Current Count: {counter.value}</p>
</div>
</main>
);
}
字符串
我知道服务器组件可以在Nextjs中使用router.refresh()
重新呈现
// app/clientComponent.tsx
'use client';
import { useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState } from '@/store';
import { increment } from '@/store/counterSlice';
import { useRouter } from 'next/navigation';
export default function ClientComponent({
children,
}: {
children: React.ReactNode;
}) {
const dispatch = useDispatch<AppDispatch>();
const count = useSelector((state: RootState) => state.counter.value);
const router = useRouter();
const handleIncrementCounter = () => {
dispatch(increment());
// this rerenders the server component
router.refresh();
};
return (
<div id='with-font-container'>
{/* this value us correctly subscribed and updated to the store changes */}
<p>Current Count: {count}</p>
<button onClick={handleIncrementCounter}>Increment Count</button>
{children}
</div>
);
}
型
两个组件都位于同一页面中,并且增量计数成功地增加了客户端中的计数,但是服务器组件保持初始值10,尽管router.refresh()
成功地重新呈现(由服务器中的console.log
确认)
// app/page.tsx
export default function Home() {
return (
<div className='bg-black text-3xl'>
<ClientComponent>
{/* this error is a known next13 bug https://github.com/vercel/next.js/issues/42292 */}
{/* @ts-expect-error Server Component */}
<ServerComponent />
</ClientComponent>
</div>
);
}
型
这意味着RSC将永远无法访问 updated redux存储(或任何其他全局存储),对吗?
这是code,以防你好奇
2条答案
按热度按时间ws51t4hk1#
是的,我相信因为RSC存在于服务器上,它的redux示例在服务器端是活动的,并且永远不会被运行在最终用户浏览器中的完全独立的redux示例更新。RSC不应该/不允许
useEffect
或useState
。如果你在ServerComponent
中使用了react-redux中的useDispatch
,这是你应该使用Redux的方式,而不是像在那里那样直接导入商店,那么构建就会失败,因为useStore/useDispatch调用了useEffect和/或useState。我希望在另一个答案中看到的是有人演示如何从根本上实现OP试图实现的目标:在服务器上获取一些数据,然后在数据源更新时让RSC重新呈现。
在RSC文档中,它提到RSC的刷新序列快乐路径需要由框架实现。因此,Next.js和Remix会对这个问题给出具体的答案。如果能看到一个答案,详细说明在Next.js和Remix中是如何做到这一点的,那就太好了。
pbossiut2#
问题是服务器存储和客户端存储不同步。
route.refresh
正在重新呈现,将服务器组件和客户端组件发送到客户端。但是当你在客户端时,当你点击increment
来更新redux商店时,那个服务器组件已经在服务器上呈现了,它不能访问客户端代码或客户端商店。如果您在
pages
目录中使用next-redux-wrapper
包设置redux,则在切片中设置了hydrate
操作字符串
在
getServerSideProps
中,我们获取数据,填充存储并将此存储发送到客户端,然后客户端使用服务器存储数据创建新存储。在本例中,我们向客户端发送一个已经获取并填充的存储,客户端可以访问它。但在您的示例中,每次在服务器组件上调用
store.getState().counter
时,您都希望从存储在Provider中的客户端存储中读取数据,而访问此Provider的唯一方法是从客户端使用useSelector
钩子