🐧

【SolidJS】propsを分割代入してハマった話

2022/11/13に公開

起きていたこと

以下のようなコードを書いていたが、一向にUsersがfetchされたあともUserComponentの値が更新されず困っていた。Reactと同様であれば、propsが更新されたタイミングでレンダリングが走るはずだと思いこんでいたのだが大きく違った。
なお使用しているコードはサンプルのため、単純化している。

コード

const Home = () => {
    const [users] = createResource(fetchUsers)
    
    return (<Users users={users() ?? []}></Users>)
}

const Users = ({users}: {users: User[]}) => {
    const view = createMemo(users.map((user) => <div>user.name</div>),[users])
    return view
}

原因

  • 原因はUsersのコンポーネントでpropsを分割代入していたことによって、差分を検知するための追跡スコープから逃れてしまっていた模様。
  • Reactのような単純な分割代入はNG。
  • 他にもスプレッド演算子等によるPropsの代入もNG。

参考:
https://www.solidjs.com/tutorial/props_defaults

改善コード

const Home = () => {
    const [users] = createResource(fetchUsers)
    
    return (<Users users={users() ?? []}></Users>)
}

const Users = (props:{users: User[]}) => {
    const view = createMemo(props.users.map((user) => <div>user.name</div>),[users])
    return view
}

propsを扱うその他の便利なメソッド

  1. mergeProps
    Object.assignのように、2つのオブジェクトを結合します。
import { mergeProps } from "solid-js";

const merged = mergeProps({ lastName: "hoge", firstName: "fuga" }, props);

2.splitProps
分割代入をやるために利用できる。

export const User = (props) => {
  const [local, others] = splitProps(props, ["lastName", "firstName"]);
  return <h3 {...others}>{local.greeting} {local.name}</h3>
}

おわりに

Solid.jsを触り始めてみましたが、Reactと同じ部分と違う部分が散見されます。ただ、たしかに「この処理や計算がないのか!」と感じる部分も多く、パフォーマンス良さげなのがコーディングしていても感じられてきます。もう少し勉強してみます🔥

Discussion