💡
SvelteでReactのforwardRef的なことのやり方
カスタムコンポーネントにref propを渡して参照取りたい時にreactのforwardRef的なのがsvelteにないかなと思って、色々調べていくつか方法見つけたので、残しておきます。
Reactの場合
import * as React from 'react';
// Parent.jsx
const Parent = () => {
const ref = React.useRef(null);
React.useEffect(() => {
if(ref.current) {
ref.current.focus();
}
},[]);
return (<Child ref={ref}/>);
}
// Child.jsx
const Child = React.forwardRef(function Child(props, ref) {
return (<input ref={ref} />);
});
Svelteの場合
- writableを使う方法
<script>
// Parent.svelte
import Child from "./Child.svelte";
let ref;
$: {
if($ref) {
$ref.value = "hello from parent ";
}
}
</script>
<Child bind:ref={ref}/>
<script>
// Child.svelte
import { writable } from 'svelte/store';
export const ref = writable();
</script>
<input bind:this={$ref}/>
- callback prop使う方法
<script>
// Parent.svelte
import Child from "./Child.svelte";
import {onMount} from 'svelte';
let ref;
$: {
if(ref) {
ref.value = "hello from parent ";
}
}
</script>
<Child ref={(el) => (ref = el)}/>
<script>
// Child.svelte
import { writable } from 'svelte/store';
import {onMount} from 'svelte';
let el;
export let ref;
onMount(()=> {
if(ref) {
ref(el);
}
})
</script>
<input bind:this={el}/>
Discussion
記事をありがとうございます。
こちら参考までに、Writableを使わなくてもbindingできます!
変数のbindingをするだけであればstoreはtoo muchかなと思いました。
コメントありがとうございます。
そうですね、単純に値をバインディングしたいだけならそれでいいと思います。
記事の説明が悪かったですかね、どちらかというと子コンポーネントの参照が取りたいのが目的ですね。
多分👇のようになるかなと
親から直接子の関数を呼んだり、ステートを更新したりすることが目的ですね。
返信いただけて嬉しく思います。
Refにアクセスしたいという記事の趣旨は理解しております。
こちらこそ言葉足らずで申し訳ありません。
ただ、自分は数年svelteを使ってきて子要素のthisを直接参照する必要にかられたことがまずなかったです。
なので記事の例は必要以上に複雑性を上げているなという印象を持ちました(個人の感想です)。
なのでコメントさせていただきました。
上の例では
こんなかんじになるかなと
また、子の関数を直接呼ぶことも自分の経験ではなかったです。
あくまで、stateの変数を変化させると子の中でreactiveに処理が走る、という書き方をしていました。
もし具体例をいただけたらより詳細にお答えできると思います。
必要でなければ返信していただかなくても大丈夫です。お節介を失礼いたします。
返信ありがとうございます。
自分もまだsvelteは初心者でして、ずっとreactをやってきたので、最初はreactのやり方に頭が回ってしまった気がします。
reactの場合に親で子のための状態を持つと、場合によって必要としないレンダリングが走ってしまい、それを防ぐためにキャッシュを使ったり、依存関係を変えたりと苦しみられる時があって、その時はforwardRefを使って子の状態をダイレクトに変えたりしていました。
確かに、そんな複雑な事をsvelteではやる必要はなさそうでした、これもsvelteの素晴らしいところですね。
単に子の関数だけ呼びたい場合に👇のように書いてもいける事がわかりました。
ありがとうございました!
お久しぶりです。
そういえば
という書き方ができることを最近知りました。
最近になって(おそらくsvelte4から?)Svelte Componentに対して
bind:this
を取得して、そのthis
からmethodを取り出せるようになったそうです。エディタでの補完も効くのでやってみてください
お久しぶりです。
わざわざありがとう御座います。
この記事書いていた時に同じようなことを試していたような記憶もありますが、そのときはコンパイルエラーが出ていた気がします(気の所為だったのかもしれないですが)、昨日最新バージョンで試してみたら、本当にいけました!