Saya memiliki rute panggilan balik di aplikasi saya yang menerima token akses dari proses auth di fragmen hash URL. Saya ingin menguraikannya dan menyimpannya ke toko redux. Saya dulu mendapatkannya melalui window.location.hash
sebelum saya beralih ke berikutnya, tetapi ini tidak tersedia ketika halaman merender sisi server (juga fragmen hash tampaknya tidak dikirim ke server, jadi saya tidak dapat menguraikannya di sana ).
Apakah ada cara untuk membatasi beberapa kode untuk dieksekusi hanya di sisi klien? Atau adakah cara lain untuk mencapai ini?
@vanniewelt : Komponen Async yang diimpor secara dinamis dimuat pada klien dan Anda dapat meletakkan semua logika sisi klien di sana.
Siklus hidup ComponentWillReceiveProps juga akan menerima permintaan di props saat berada di sisi server.
Dapat memeriksa apakah variabel ini ada dan menyuntikkan kode klien Anda.
Jika lib membutuhkan variabel jendela, saya sarankan Anda menggunakan impor Dinamis, berfungsi dengan baik untuk saya.
https://github.com/zeit/next.js/tree/v3-beta/examples/with-dynamic-import
Anda juga dapat menggunakan metode siklus hidup componentDidMount
dari React. Itu tidak disebut sisi server.
@vanniewelt Anda selalu dapat melihat process.browser
..
if (process.browser) {
// client-side-only code
}
diedit oleh @Timer :
@vanniewelt Anda selalu dapat melihat typeof window
..
if (typeof window !== 'undefined') {
// client-side-only code
}
ya tapi itu bukan pendekatan terbaik.
katakanlah saya ingin memeriksa apakah pengguna diautentikasi, dan saya ingin menjalankan pemeriksaan itu hanya di sisi klien karena beberapa alasan, salah satunya adalah karena saya menyimpan JWT di localStorage dan tidak ingin menyimpannya di cookie.
Jadi dalam hal ini pada halaman pertama memuat dengan:
if (process.browser) {
// client-side-only code
}
kode dalam ruang lingkup tidak akan dieksekusi sama sekali, bukan di server bukan di klien, itu akan dieksekusi hanya jika perubahan rute dipicu dari klien
@sarkistlt Anda mungkin benar dalam beberapa kasus tergantung di mana kode itu ditempatkan .. tapi..
Jika kode tersebut dieksekusi di server, eksekusi tidak akan mencapai // client-side-only code
. Jika kode tersebut dieksekusi pada klien, eksekusi akan mencapai // client-side-only code
.
Sepertinya jawaban yang valid untuk pertanyaan:
Apakah ada cara untuk membatasi beberapa kode untuk dieksekusi hanya di sisi klien?
@sarkistlt componentDidMount
hanya dieksekusi sisi klien, componentWillMount
dijalankan baik sisi klien maupun server.
@sarkistlt https://reactjs.org/docs/react-component.html#componentwillmount
Ini adalah satu-satunya kait siklus hidup yang dipanggil pada rendering server.
Saya melakukannya berkali-kali, Anda membingungkan componentWillMount
dengan componentDidMount
.
@sergiodxa sebenarnya Anda benar, baru saja menjalankan tes. Terima kasih!
Tautan @sergiodxa componentWillMount
diubah menjadi https://reactjs.org/docs/react-component.html#unsafe_componentwillmount.
Saya membutuhkan modul mapbox-gl
yang merupakan perpustakaan sisi klien di dalam ComponentDidMount
dan menghilangkan kesalahan jelek ReferenceError: self is not defined
Saya tidak dapat membuat Mapbox menggunakan componentDidMount
karena komponen masih mencoba untuk diproses (saya tidak tahu apa yang sebenarnya coba dilakukan) di server (saya akhirnya mengalami masalah yang sama dengan @elaich ).
Menggunakan Impor Dinamis seperti yang disarankan oleh @aga5tya berhasil .
@vanniewelt : Komponen Async yang diimpor secara dinamis dimuat pada klien dan Anda dapat meletakkan semua logika sisi klien di sana.
Siklus hidup ComponentWillReceiveProps juga akan menerima permintaan di props saat berada di sisi server.
Dapat memeriksa apakah variabel ini ada dan menyuntikkan kode klien Anda.Jika lib membutuhkan variabel jendela, saya sarankan Anda menggunakan impor Dinamis, berfungsi dengan baik untuk saya.
https://github.com/zeit/next.js/tree/v3-beta/examples/with-dynamic-import
Bagi mereka yang mengalami utas ini mencari solusi. Tautan Impor Dinamis yang tercantum di atas rusak. Ini telah diperbarui dan dapat ditemukan di Dynamic Imports .
Jika Anda memiliki komponen yang seharusnya selalu dijalankan pada klien, dan tidak ingin menggunakan Impor Dinamis (misalnya: orang dapat lupa bahwa mereka perlu menggunakannya), Anda dapat menggunakan Hooks (atau componentDidMount
setara
import React, { useEffect, useState } from 'react'
function CreateInteraction ({ input }) {
const [isComponentMounted, setIsComponentMounted] = useState(false)
useEffect(() => setIsComponentMounted(true), [])
if(!isComponentMounted) {
return null
}
return <h1>I'm only executed on the client!</h1>
}
Hanya untuk menambahkan beberapa jawaban yang sudah bagus: Proyek saya saat ini melakukan banyak rendering bersyarat di kedua arah, jadi saya menggunakan komponen untuk ini:
import React, { useEffect, useState } from "react";
export interface ConditionallyRenderProps {
client?: boolean;
server?: boolean;
}
const ConditionallyRender: React.FC<ConditionallyRenderProps> = (props) => {
const [isMounted, setIsMounted] = useState(false);
useEffect(() => setIsMounted(true), []);
if(!isMounted && props.client) {
return null;
}
if(isMounted && props.server) {
return null;
}
return props.children as React.ReactElement;
};
export default ConditionallyRender;
Dan kemudian gunakan sebagai berikut:
<Layout>
<ConditionallyRender server>
<p>This is rendered only on server.</p>
</ConditionallyRender>
<ConditionallyRender client>
<p>This is rendered only on client.</p>
</ConditionallyRender>
</Layout>
Jika Anda menggunakan perpustakaan apa pun yang mengakses API browser, maka Anda dapat mengimpor modul secara dinamis dengan SSR=false sebagai argumen kedua.
const DynamicComponentWithNoSSR = dynamic(
() => import('../components/hello3'),
{ ssr: false }
)
https://nextjs.org/docs/advanced-features/dynamic-import
Jika Anda menggunakan perpustakaan apa pun yang mengakses API browser, maka Anda dapat mengimpor modul secara dinamis dengan SSR=false sebagai argumen kedua.
const DynamicComponentWithNoSSR = dynamic( () => import('../components/hello3'), { ssr: false } )
https://nextjs.org/docs/advanced-features/dynamic-import
Anda juga perlu menambahkan impor ini jika Anda ingin menggunakan impor "dinamis" untuk siapa pun yang melihat kode @yashwant-dangi!
import dynamic from 'next/dynamic'
@Timer Saya perhatikan Anda mengedit komentar saya https://github.com/vercel/next.js/issues/2473#issuecomment -362119102, yang saya edit lagi untuk mencerminkan komentar asli dan hasil edit Anda.
typeof window !== 'undefined'
bukan hanya process.browser
? Ini lebih bertele-tele, jadi jika tidak ada alasan di sini, saya lebih suka menggunakan process.browser
.Mengapa kita harus menggunakan typeof window !== 'undefined' bukan hanya process.browser? Ini lebih bertele-tele, jadi jika tidak ada alasan di sini, saya lebih suka menggunakan process.browser.
process.browser
tidak standar dan hanya tersedia di lingkungan webpack, artinya kemungkinan akan rusak di masa mendatang, misalnya webpack 5 tidak lagi polyfills process
.
Alternatif untuk typeof window !== "undefined"
bisa menjadi Object.prototype.isPrototypeOf(window)
. Berdasarkan posting ini , bagaimanapun, bundel yang diproduksi oleh Next.js mendeteksi bundel sebelumnya dan apa pun yang menghasilkan bundel yang lebih ringan harus dianggap sebagai kemenangan.
Komentar yang paling membantu
@vanniewelt Anda selalu dapat melihat
process.browser
..diedit oleh @Timer :
@vanniewelt Anda selalu dapat melihat
typeof window
..