Saya mencoba untuk mengubah <canvas>
animasi keren yang saya temukan di sini menjadi komponen React yang dapat digunakan kembali. Sepertinya komponen ini memerlukan satu komponen induk untuk kanvas, dan banyak komponen anak untuk function Ball()
.
Untuk alasan kinerja, mungkin akan lebih baik untuk menjadikannya Balls
komponen tanpa negara karena jumlahnya akan banyak. Saya tidak begitu familiar dengan membuat komponen stateless dan bertanya-tanya di mana saya harus mendefinisikan this.update()
dan this.draw
fungsi yang didefinisikan function Ball()
.
Apakah fungsi untuk komponen stateless masuk ke dalam atau ke luar komponen? Dengan kata lain, manakah dari berikut ini yang lebih baik?
1:
const Ball = (props) => {
const update = () => {
...
}
const draw = () => {
...
}
return (
...
);
}
2:
function update() {
...
}
function draw() {
...
}
const Ball = (props) => {
return (
...
);
}
Apa pro / kontra dari masing-masing dan apakah salah satunya lebih baik untuk kasus penggunaan tertentu seperti saya?
Jawaban:
Hal pertama yang perlu diperhatikan adalah bahwa komponen fungsional stateless tidak dapat memiliki metode, Anda tidak boleh mengandalkan panggilan
update
ataudraw
renderBall
jika itu adalah komponen fungsional stateless.Dalam kebanyakan kasus, Anda harus mendeklarasikan fungsi di luar fungsi komponen sehingga Anda mendeklarasikannya hanya sekali dan selalu menggunakan kembali referensi yang sama. Saat Anda mendeklarasikan fungsi di dalamnya, setiap kali komponen dirender, fungsi tersebut akan ditentukan lagi.
Ada beberapa kasus di mana Anda perlu mendefinisikan fungsi di dalam komponen untuk, misalnya, menetapkannya sebagai pengendali kejadian yang berperilaku berbeda berdasarkan properti komponen. Tapi tetap saja Anda bisa mendefinisikan fungsi di luar
Ball
dan mengikatnya dengan properti, membuat kode lebih bersih dan membuat fungsiupdate
ataudraw
dapat digunakan kembali.// You can use update somewhere else const update (propX, a, b) => { ... }; const Ball = props => ( <Something onClick={update.bind(null, props.x)} /> );
Jika Anda menggunakan hook , Anda bisa menggunakan
useCallback
untuk memastikan fungsi hanya didefinisikan ulang ketika salah satu dependensinya (props.x
dalam kasus ini) berubah:const Ball = props => { const onClick = useCallback((a, b) => { // do something with a, b and props.x }, [props.x]); return ( <Something onClick={onClick} /> ); }
Ini cara yang salah :
const Ball = props => { function update(a, b) { // props.x is visible here } return ( <Something onClick={update} /> ); }
Saat menggunakan
useCallback
, mendefinisikanupdate
fungsi dalamuseCallback
kait itu sendiri di luar komponen menjadi keputusan desain lebih dari apa pun, Anda harus mempertimbangkan jika Anda akan menggunakan kembaliupdate
dan / atau jika Anda perlu mengakses ruang lingkup penutupan komponen, misalnya, baca / tulis negara. Secara pribadi saya memilih untuk mendefinisikannya di dalam komponen secara default dan membuatnya dapat digunakan kembali hanya jika diperlukan, untuk mencegah rekayasa berlebihan dari awal. Selain itu, menggunakan kembali logika aplikasi lebih baik dilakukan dengan hook yang lebih spesifik, meninggalkan komponen untuk tujuan presentasi. Mendefinisikan fungsi di luar komponen saat menggunakan hook benar-benar bergantung pada nilai decoupling dari React yang Anda inginkan untuk logika aplikasi Anda.sumber
this.draw
fungsi di dalam fileBall
. Ini menggunakanctx
from apa yang akan menjadi induk<canvas>
dan juga menggunakanthis
kata kunci untuk apa yang akan menjadiBall
komponen anak . Apa cara terbaik untuk mengintegrasikan implementasi komponen stateless sehingga kedua properti tersebut dapat diakses?this
saat menggunakan komponen fungsional tanpa negara, ingatlah itu. Untuk konteks kanvas, Anda harus meneruskannya ke setiap singleBall
, kedengarannya tidak bagus sama sekali.bind
secara khusus di Chrome lebih awal dari 59 bahkan lebih lambat dari fungsi panah. Dan di Firefox cukup lama karena keduanya bekerja dengan kecepatan yang sama. Jadi saya akan mengatakan dalam kasus seperti itu tidak ada perbedaan cara mana yang disukai :)Something
komponen untuk mengetahui bahwa ada prop X di komponen induknya karena membuatnya sadar akan konteksnya. Hal yang sama terjadi untuk pertanyaan yang Anda tanyakan dan kode contoh yang saya tulis, itu tergantung pada konteksnya, yang diabaikan demi kesederhanaan.Kita dapat memiliki fungsi di dalam komponen fungsional tanpa kewarganegaraan, berikut contohnya:
const Action = () => { function handlePick(){ alert("test"); } return ( <div> <input type="button" onClick={handlePick} value="What you want to do ?" /> </div> ); }
Namun, ini bukan praktik yang baik karena fungsi
handlePick()
akan ditentukan setiap kali komponen dipanggil.sumber
handlePick()
atas / di luar komponen sepertifunction handlePick() { ... }; const Action = () => { ... }
hasil yang handlePick hanya didefinisikan sekali. Jika Anda membutuhkan data dariAction
komponen, Anda harus meneruskannya sebagai parameter kehandlePick
fungsi.Kita dapat menggunakan hook React
useCallback
seperti di bawah ini dalam komponen fungsional:const home = (props) => { const { small, img } = props const [currentInd, setCurrentInd] = useState(0); const imgArrayLength = img.length - 1; useEffect(() => { let id = setInterval(() => { if (currentInd < imgArrayLength) { setCurrentInd(currentInd => currentInd + 1) } else { setCurrentInd(0) } }, 5000); return () => clearInterval(id); }, [currentInd]); const onLeftClickHandler = useCallback( () => { if (currentInd === 0) { } else { setCurrentInd(currentInd => currentInd - 1) } }, [currentInd], ); const onRightClickHandler = useCallback( () => { if (currentInd < imgArrayLength) { setCurrentInd(currentInd => currentInd + 1) } else { } }, [currentInd], ); return ( <Wrapper img={img[currentInd]}> <LeftSliderArrow className={currentInd > 0 ? "red" : 'no-red'} onClick={onLeftClickHandler}> <img src={Icon_dir + "chevron_left_light.png"}></img> </LeftSliderArrow> <RightSliderArrow className={currentInd < imgArrayLength ? "red" : 'no-red'} onClick={onRightClickHandler}> <img src={Icon_dir + "chevron_right_light.png"}></img> </RightSliderArrow> </Wrapper>); } export default home;
Saya mendapatkan 'img' dari induknya dan itu adalah sebuah array.
sumber
Jika Anda ingin menggunakan props atau status komponen dalam fungsi, itu harus didefinisikan dalam komponen dengan useCallback.
function Component(props){ const onClick=useCallback(()=>{ // Do some things with props or state },[]) }
Di sisi lain, jika Anda tidak ingin menggunakan props atau state in function, tentukan di luar komponen.
const computeSomethings=()=>{ // Do some things with params or side effects } function Component(props){ }
sumber