npm set-value と useReducer を組み合わせて柔軟にフィールドを更新する
Gaji-Labo フロントエンドエンジニアの茶木です。
本記事では React の useReducer
と npm set-value の組み合わせの少し便利なテクニックを模索し、共有したいと思います。
具体的な適用範囲は限定的なのですが、たとえばカスタムフィールドなど、フォームの編集を useReducer
で管理し、インプット項目自体が可変で生成され、データを保持するようなケースでは有用と考えます。
set-value とは
import sv from "set-value";
const object = { a: b: c: false };
sv(object, "a.b.c", true);
console.log(object.a.b.c); // true
set-value
は特段新しいライブラリではないのですが、特記すべきポイントがあります。
それが sv
の第2引数で、第1引数のオブジェクトに対して、.
区切りでネストを潜っていき終端のキーに対して、第3引数の値を代入できます。
これだけだと、
object.a.b.c = true
と指定するのと同じなので、これだけでは set-value の有用性はあまり感じられません。 しかし「ネストのパス」を string で表現し処理できるのが便利なケースがあります。
useReducer で汎用の値を更新するケース
set-value
を便利に使う例です。
interface State {
id: ...
metaField: Object,
}
type Action =
| {
type: "set:meta_field_value";
payload: { keyPath: string, value: any };
}
| { ......
const reducer: Reducer<State, Action> = (
state: State,
action: Action
) => {
switch (action.type) {
case "set:meta_field_value": {
const { keyPath, value } = action.payload;
const newState = { ...state };
sv(newState, keyPath, value);
return newState;
}
case ......
metaField
の内部はネストが深く複雑で、事前に型がわからない、あるいは指定が困難である場合です。たとえば、JSONから生成されたオブジェクトなどで組み合わせが多く、型定義が難しいオブジェクト操作を想定しています。
const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
dispatch({
type: "set:meta_field_value",
payload: {
keyPath: "relationalImage.thumbnail.alt",
value: "2024 MetaField",
}
);
dispatch
で keyPath
を指定し、metaField
の中の任意の値を変更できます。
これは他の方法では、ちょっと実現しにくいのではないでしょうか。
注意点
この dispatch
の payload
に keyPath
を渡してオブジェクトを変更する方法は、冒頭で述べたように、カスタムフィールドのような、キー名も型も何種類もパターンがあるようなケースでのみ使うべきと考えます。柔軟性が高い分、自由にオブジェクトを変更できてしまうからです。
そのため、オブジェクトの型が明確で操作する値の把握ができているほとんどのケースでは keyPath
を payload
に渡さず従来の方法で変更する方が、型指定も明確になり安全で読みやすいコードになります。
おわりに
本記事では少し特殊な柔軟性の高いオブジェクト操作のテクニックについて模索しました。
スタートアップの成長支援をしている Gaji-Labo では、エンジニアは、柔軟性の高いコードも堅牢なコードも事業のフェーズや状況にあわせて選択しています。支援の基礎力である技術的な研鑽を忘れず、プロジェクトの加速に貢献していきたいです。
Gaji-Labo は新規事業やサービス開発に取り組む、事業会社・スタートアップへの支援を行っています。
弊社では、Next.js を用いた Web アプリケーションのフロントエンド開発をリードするフロントエンドエンジニアを募集しています!さまざまなプロダクトやチームに関わりながら、一緒に成長を体験しませんか?
もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください!