#reactjs #react-hooks #next.js
#reactjs #реагирующие крючки #next.js
Вопрос:
Я создаю проект, используя next.js но у меня есть проблема, связанная с тем, что getServerSideProps вызывается 6 раз при рендеринге страницы.
Вот код в верхней части страницы.
const NewFindstay: React.FC<INewFindstayProps> = ({ findstayList }) => {
const [isMap, setIsMap] = useState(false);
return (
<div id="contents">
<FindstayFilter setIsMap={setIsMap} isMap={isMap} />
<FindstayList findstayList={findstayList} isMap={isMap} />
</div>
);
};
export async function getServerSideProps({ query, req }) {
let findstayList = null;
try {
findstayList = await getPlaceListAsync(
{ ...query },
req.headers.cookie ? req.headers.cookie : null
);
} catch (e) {
findstayList = null;
}
return {
props: {
findstayList,
query,
},
};
}
export default NewFindstay;
Кажется, это вызвано компонентами, которые импортированы внутри FindstayFilter. (допустим, компоненты A, B, C, D, E, F)
Каждый компонент A, B, C, D, E, F имеет хук useEffect для setState .
// A
useEffect(() => {
if (router.query.city) {
setSelectedCity(router.query.city);
};
}, [router.query.city]);
// B
useEffect(() => {
setDateRange({
startDate: check_in ? moment(check_in) : null,
endDate: check_out ? moment(check_out) : null
})
}, [router.query.check_in, router.query.check_out]);
// C
useEffect(() => {
const queryPrice = {
min: price_min ? (parseInt(price_min as string, 10) / 10000) : 0,
max: price_max ? (parseInt(price_max as string, 10) / 10000) : 100
}
setRangePrice(queryPrice);
}, [router.query.price_min, router.query.price_max]);
// D, E, F use same pattern as well.
Другими словами, когда компонент FindstayFilter выполняет рендеринг, useEffect hook внутри A, B, C, D, E, F повторно отображает компонент всего 6 раз, что также вызывает вызов getServerSideProps 6 раз.
Как я могу минимизировать вызов getServerSideProps? должен ли я использовать хук useEffect только внутри компонента FindstayFilter и набивать много кода setstate в хук?
Ответ №1:
getServerSideProps
вызывается только при первой загрузке страницы, потому что он вызовет сервер nodejs nextjs. Это всегда будет иметь место, независимо от того, что, если вы не выполните перезагрузку / обновление страницы. https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering
Ответ №2:
Я нашел, что было не так.
Я помещаю хук useEffect с состоянием массива зависимостей внутри в каждый компонент, чтобы при каждом изменении состояний router.push работал.
const pushRouter = (renderQuery) => {
return (
router.push({
pathname: "/findstay",
query: {
...router.query,
...renderQuery,
page: 1,
per: 10
}
})
);
};
useEffect(() => {
const queryCnt = {
adultCnt: adult_cnt ? parseInt(adult_cnt as string, 10) : 0,
childCnt: child_cnt ? parseInt(child_cnt as string, 10) : 0,
babyCnt: baby_cnt ? parseInt(baby_cnt as string, 10) : 0
};
pushRouter(queryCnt)
}, [adult_cnt, child_cnt, baby_cnt]);
Однако router.push работает как ssr в моем коде (предполагается, что он работает как csr), что означает, что при рендеринге FindstayFilter функция pushRouter в дочерних компонентах A, B, C, D, E, F также работает, и это приводит к рендерингу getServerSideProps 6 раз.
Теперь я должен найти причину, по которой router.push работает ssr https://github.com/vercel/next.js/issues/9586