【ReactFlow】Cannot assign to read only property 'width' of object '#<Object>' TypeError: Cannot assign to read only property 'width' of object '#<Object>'のエラーがでて画面の拡大縮小ができないときにしたこと

# エラー
```
Cannot assign to read only property 'width' of object '#<Object>'
TypeError: Cannot assign to read only property 'width' of object '#<Object>'
    at applyChange (http://localhost:3000/static/js/bundle.js:99275:34)
    at applyChanges (http://localhost:3000/static/js/bundle.js:99247:7)
    at applyNodeChanges (http://localhost:3000/static/js/bundle.js:99310:10)
    at http://localhost:3000/main.3efe227f07ece2d34852.hot-update.js:81:175
    at valueFromValueOrUpdater (http://localhost:3000/static/js/bundle.js:86778:12)
    at applyAction (http://localhost:3000/static/js/bundle.js:86789:22)
    at http://localhost:3000/static/js/bundle.js:86842:7
    at Object.replaceState (http://localhost:3000/static/js/bundle.js:88223:18)
    at applyActionsToStore (http://localhost:3000/static/js/bundle.js:86839:9)
    at queueOrPerformStateUpdate (http://localhost:3000/static/js/bundle.js:86858:5)
```

# 該当コード(再現)
以下、公式ドキュメント[^公式ドキュメント]を参考にして再現した該当コードです。

```typescript
import { useCallback, useState } from 'react';
import { ReactFlow, applyEdgeChanges, applyNodeChanges } from '@xyflow/react';
import { useRecoilState } from 'recoil';
import '@xyflow/react/dist/style.css';

const initialNodes = [
    {
        id: '1',
        type: 'input',
        data: { label: 'Input Node' },
        position: { x: 250, y: 25 },
    },
    
    {
        id: '2',
        // you can also pass a React component as a label
        data: { label: <div>Default Node</div> },
        position: { x: 100, y: 125 },
    },
    {
        id: '3',
        type: 'output',
        data: { label: 'Output Node' },
        position: { x: 250, y: 250 },
    },
];

 const initialEdges = [
     { id: 'e1-2', source: '1', target: '2' },
     { id: 'e2-3', source: '2', target: '3', animated: true },
];


function Flow() {
    const [nodes, setNodes] = useRecoilState(initialNodes);
    const [edges, setEdges] = useRecoilState(initialEdges);

    const onNodesChange = useCallback(
        (changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
        [setNodes],
    );
    const onEdgesChange = useCallback(
        (changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
        [setEdges],
    );

    return (
        <ReactFlow
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            fitView
        />
    );
}

export default Flow;
```

# 考えられる原因
nodeの中のmesuredの中のwidthが読み取り専用になっていることが原因でapplyChange関数内において書き換えができないこと。
なぜ読み取り専用になっているかはよく分かっていないが、useStateを使っている公式ドキュメント[^公式ドキュメント]ではエラーは出ないことからuseRecoilStateを使っていることが原因だと思っている。
[^公式ドキュメント]: Core Concepts. React Flow. https://reactflow.dev/learn/concepts/core-concepts.

# 解決するためにしたこと
mesured.widthとmesured.heightのプロパティをコピーして使うようにすることで書き換えも可能にした。

```typescript
// ノードの変更を検知
const onNodesChange = useCallback(
    async (changes: any) => {
        // changes: "dimensions" | "remove" | "select" | "position"
        setNodes((nodes) => {
            const oldNodes = nodes.map(
                (node) => ({
                    ...node,
                    measured: {
                        width: node.measured?.width || 150,
                        height: node.measured?.height || 38,
                    }
                })
            );
            return applyNodeChanges(changes, oldNodes);
        });
    },
    [setNodes],
);
```

:::note warn
Recoilの設定で書き込みの設定がもしできるのであればそっちの方がきれいかもしれません。
:::