質問編集履歴
16
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -284,7 +284,6 @@
|
|
|
284
284
|
|
|
285
285
|
# 試したこと6
|
|
286
286
|
「試したこと5」の `memo` を利用する必要がないことに気付いたので修正しました。
|
|
287
|
-
|
|
288
287
|
```tsx
|
|
289
288
|
import { useState } from 'react'
|
|
290
289
|
|
|
@@ -324,6 +323,7 @@
|
|
|
324
323
|
|
|
325
324
|
# 試したこと7
|
|
326
325
|
handleChangeName と handleChangePassword を共通化しました。
|
|
326
|
+
name の指定が少し長くなっていますが型安全の為です。仕方ないです。
|
|
327
327
|
|
|
328
328
|
```tsx
|
|
329
329
|
import { useState } from 'react'
|
|
@@ -334,6 +334,8 @@
|
|
|
334
334
|
password: ''
|
|
335
335
|
})
|
|
336
336
|
|
|
337
|
+
type FormKeys = keyof typeof form
|
|
338
|
+
|
|
337
339
|
function handleSubmit(e: React.SubmitEvent<HTMLFormElement>) {
|
|
338
340
|
e.preventDefault()
|
|
339
341
|
|
|
@@ -348,10 +350,10 @@
|
|
|
348
350
|
return (
|
|
349
351
|
<form onSubmit={handleSubmit}>
|
|
350
352
|
<div>
|
|
351
|
-
<input name={"name" satisfies
|
|
353
|
+
<input name={"name" satisfies FormKeys} value={form.name} onChange={handleChange} />
|
|
352
354
|
</div>
|
|
353
355
|
<div>
|
|
354
|
-
<input name={"password" satisfies
|
|
356
|
+
<input name={"password" satisfies FormKeys} value={form.password} onChange={handleChange} />
|
|
355
357
|
</div>
|
|
356
358
|
|
|
357
359
|
<input type="submit" />
|
15
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -348,10 +348,10 @@
|
|
|
348
348
|
return (
|
|
349
349
|
<form onSubmit={handleSubmit}>
|
|
350
350
|
<div>
|
|
351
|
-
<input name="name" value={form.name} onChange={handleChange} />
|
|
351
|
+
<input name={"name" satisfies keyof typeof form} value={form.name} onChange={handleChange} />
|
|
352
352
|
</div>
|
|
353
353
|
<div>
|
|
354
|
-
<input name="password" value={form.password} onChange={handleChange} />
|
|
354
|
+
<input name={"password" satisfies keyof typeof form} value={form.password} onChange={handleChange} />
|
|
355
355
|
</div>
|
|
356
356
|
|
|
357
357
|
<input type="submit" />
|
14
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -236,8 +236,129 @@
|
|
|
236
236
|
</form>
|
|
237
237
|
)
|
|
238
238
|
}
|
|
239
|
+
```
|
|
239
240
|
|
|
241
|
+
# 試したこと5
|
|
242
|
+
setValue に直接 setter を指定して「試したこと3」を改良しました。
|
|
243
|
+
関数オブジェクトが再生成されないようになりました。
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
import { memo, useState } from 'react'
|
|
247
|
+
|
|
248
|
+
interface Props {
|
|
249
|
+
value: string
|
|
250
|
+
setValue: (value: string) => void
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function Input(props: Props) {
|
|
254
|
+
return (
|
|
255
|
+
<div>
|
|
256
|
+
<input value={props.value} onChange={(e) => props.setValue(e.target.value)} />
|
|
257
|
+
</div>
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const MemoInput = memo(Input)
|
|
262
|
+
|
|
263
|
+
export default function App() {
|
|
264
|
+
const [name, setName] = useState('')
|
|
265
|
+
const [password, setPassword] = useState('')
|
|
266
|
+
|
|
267
|
+
function handleSubmit(e: React.SubmitEvent<HTMLFormElement>) {
|
|
268
|
+
e.preventDefault()
|
|
269
|
+
|
|
270
|
+
console.log(`name is ${name}`)
|
|
271
|
+
console.log(`password is ${password}`)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
<form onSubmit={handleSubmit}>
|
|
276
|
+
<MemoInput value={name} setValue={setName} />
|
|
277
|
+
<MemoInput value={password} setValue={setPassword} />
|
|
278
|
+
|
|
279
|
+
<input type="submit" />
|
|
280
|
+
</form>
|
|
281
|
+
)
|
|
282
|
+
}
|
|
240
283
|
```
|
|
241
284
|
|
|
285
|
+
# 試したこと6
|
|
286
|
+
「試したこと5」の `memo` を利用する必要がないことに気付いたので修正しました。
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import { useState } from 'react'
|
|
290
|
+
|
|
291
|
+
export default function App() {
|
|
292
|
+
const [name, setName] = useState('')
|
|
293
|
+
const [password, setPassword] = useState('')
|
|
294
|
+
|
|
295
|
+
function handleSubmit(e: React.SubmitEvent<HTMLFormElement>) {
|
|
296
|
+
e.preventDefault()
|
|
297
|
+
|
|
298
|
+
console.log(`name is ${name}`)
|
|
299
|
+
console.log(`password is ${password}`)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function handleChangeName(e: React.ChangeEvent<HTMLInputElement>) {
|
|
303
|
+
setName(e.target.value)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function handleChangePassword(e: React.ChangeEvent<HTMLInputElement>) {
|
|
307
|
+
setPassword(e.target.value)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return (
|
|
311
|
+
<form onSubmit={handleSubmit}>
|
|
312
|
+
<div>
|
|
313
|
+
<input name="name" value={name} onChange={handleChangeName} />
|
|
314
|
+
</div>
|
|
315
|
+
<div>
|
|
316
|
+
<input name="password" value={password} onChange={handleChangePassword} />
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
<input type="submit" />
|
|
320
|
+
</form>
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
# 試したこと7
|
|
326
|
+
handleChangeName と handleChangePassword を共通化しました。
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
import { useState } from 'react'
|
|
330
|
+
|
|
331
|
+
export default function App() {
|
|
332
|
+
const [form, setForm] = useState({
|
|
333
|
+
name: '',
|
|
334
|
+
password: ''
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
function handleSubmit(e: React.SubmitEvent<HTMLFormElement>) {
|
|
338
|
+
e.preventDefault()
|
|
339
|
+
|
|
340
|
+
console.log(`name is ${form.name}`)
|
|
341
|
+
console.log(`password is ${form.password}`)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
|
345
|
+
setForm({ ...form, [e.target.name]: e.target.value })
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<form onSubmit={handleSubmit}>
|
|
350
|
+
<div>
|
|
351
|
+
<input name="name" value={form.name} onChange={handleChange} />
|
|
352
|
+
</div>
|
|
353
|
+
<div>
|
|
354
|
+
<input name="password" value={form.password} onChange={handleChange} />
|
|
355
|
+
</div>
|
|
356
|
+
|
|
357
|
+
<input type="submit" />
|
|
358
|
+
</form>
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
242
363
|
### 補足情報(FW/ツールのバージョンなど)
|
|
243
364
|
- React 19.2.4
|
13
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
### 試したこと4
|
|
178
178
|
`useCallback` を利用して「試したこと3」を改良しました。
|
|
179
179
|
値を変更すると「AppとNameInput」または「AppとPasswordInput」のように個別にレンダリングできるようになりました。
|
|
180
|
-
Appが再レンダリングされる事は useState が存在するので仕方ないようです。
|
|
180
|
+
Appが再レンダリングされる事は App 内に useState が存在するので仕方ないようです。
|
|
181
181
|
しかし、たった2つのinputですが、これだけ大量のコードを書かなくてはいけないのでしょうか?
|
|
182
182
|
とても大変です。なにか良い方法はないですか?
|
|
183
183
|
|
12
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
|
|
177
177
|
### 試したこと4
|
|
178
178
|
`useCallback` を利用して「試したこと3」を改良しました。
|
|
179
|
-
値を変更すると「AppとNameInput」または「AppとPasswordInput」のように個別にレンダリングできるように
|
|
179
|
+
値を変更すると「AppとNameInput」または「AppとPasswordInput」のように個別にレンダリングできるようになりました。
|
|
180
180
|
Appが再レンダリングされる事は useState が存在するので仕方ないようです。
|
|
181
181
|
しかし、たった2つのinputですが、これだけ大量のコードを書かなくてはいけないのでしょうか?
|
|
182
182
|
とても大変です。なにか良い方法はないですか?
|
11
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -174,5 +174,70 @@
|
|
|
174
174
|
}
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
+
### 試したこと4
|
|
178
|
+
`useCallback` を利用して「試したこと3」を改良しました。
|
|
179
|
+
値を変更すると「AppとNameInput」または「AppとPasswordInput」のように個別にレンダリングできるように鳴りました。
|
|
180
|
+
Appが再レンダリングされる事は useState が存在するので仕方ないようです。
|
|
181
|
+
しかし、たった2つのinputですが、これだけ大量のコードを書かなくてはいけないのでしょうか?
|
|
182
|
+
とても大変です。なにか良い方法はないですか?
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { memo, useCallback, useState } from 'react'
|
|
186
|
+
|
|
187
|
+
interface Props {
|
|
188
|
+
value: string
|
|
189
|
+
setValue: (value: string) => void
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function NameInput(props: Props) {
|
|
193
|
+
return (
|
|
194
|
+
<div>
|
|
195
|
+
<input name="name" value={props.value} onChange={(e) => props.setValue(e.target.value)} />
|
|
196
|
+
</div>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function PasswordInput(props: Props) {
|
|
201
|
+
return (
|
|
202
|
+
<div>
|
|
203
|
+
<input name="password" value={props.value} onChange={(e) => props.setValue(e.target.value)} />
|
|
204
|
+
</div>
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const MemoNameInput = memo(NameInput)
|
|
209
|
+
const MemoPasswordInput = memo(PasswordInput)
|
|
210
|
+
|
|
211
|
+
export default function App() {
|
|
212
|
+
const [name, setName] = useState('')
|
|
213
|
+
const [password, setPassword] = useState('')
|
|
214
|
+
|
|
215
|
+
function handleSubmit(e: React.SubmitEvent<HTMLFormElement>) {
|
|
216
|
+
e.preventDefault()
|
|
217
|
+
|
|
218
|
+
console.log(`name is ${name}`)
|
|
219
|
+
console.log(`password is ${password}`)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const handleSetName = useCallback((value: string) => {
|
|
223
|
+
setName(value)
|
|
224
|
+
}, [])
|
|
225
|
+
|
|
226
|
+
const handleSetPassword = useCallback((value: string) => {
|
|
227
|
+
setPassword(value)
|
|
228
|
+
}, [])
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<form onSubmit={handleSubmit}>
|
|
232
|
+
<MemoNameInput value={name} setValue={handleSetName} />
|
|
233
|
+
<MemoPasswordInput value={password} setValue={handleSetPassword} />
|
|
234
|
+
|
|
235
|
+
<input type="submit" />
|
|
236
|
+
</form>
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
|
|
177
242
|
### 補足情報(FW/ツールのバージョンなど)
|
|
178
243
|
- React 19.2.4
|
10
a
title
CHANGED
|
@@ -1,1 +1,1 @@
|
|
|
1
|
-
Reactのコンポーネントの再レンダリングを防止したい
|
|
1
|
+
Reactのコンポーネントの不必要な再レンダリングを防止したい
|
body
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
### 実現したいこと
|
|
2
|
-
Reactのコンポーネントの再レンダリングを防止したいです。
|
|
2
|
+
Reactのコンポーネントの不必要な再レンダリングを防止したいです。
|
|
3
3
|
|
|
4
4
|
### 発生している問題
|
|
5
5
|
name, password どちらか1文字でも値を変更するとApp自体が再レンダリングされてしまいます。
|
9
あ
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
useState が原因で再レンダリングされているので、そもそも useState を利用しないようにしました。
|
|
90
90
|
handleSubmit で name, password の値が取得できていますが React として適切な書き方なのかが疑問です。
|
|
91
91
|
どちらかというと今までの古き良きHTML + JavaScriptのような書き方を彷彿とさせます。
|
|
92
|
+
この書き方で問題ないならそもそも useState の存在理由も疑問に思えてきます。
|
|
92
93
|
|
|
93
94
|
また、useEffect であればエディタの名前変更機能を利用すれば自動的に全ての変数名が変更されますが、FormDataの場合は必ず手動でname属性と formData.get を修正する必要があります。
|
|
94
95
|
フォームが複雑になると人為的ミスをする可能性も出てくるので避けたいです。
|
8
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
### 発生している問題
|
|
5
5
|
name, password どちらか1文字でも値を変更するとApp自体が再レンダリングされてしまいます。
|
|
6
6
|
|
|
7
|
-
Reactの再レンダリングが発生しているかは [React Developer Tools](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) を利用して視覚的に確認しています。
|
|
7
|
+
Reactのコンポーネントの再レンダリングが発生しているかは [React Developer Tools](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) を利用して視覚的に確認しています。
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
7
a
title
CHANGED
|
@@ -1,1 +1,1 @@
|
|
|
1
|
-
Reactの再レンダリングを防止したい
|
|
1
|
+
Reactのコンポーネントの再レンダリングを防止したい
|
body
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
### 実現したいこと
|
|
2
|
-
Reactの再レンダリングを防止したいです。
|
|
2
|
+
Reactのコンポーネントの再レンダリングを防止したいです。
|
|
3
3
|
|
|
4
4
|
### 発生している問題
|
|
5
5
|
name, password どちらか1文字でも値を変更するとApp自体が再レンダリングされてしまいます。
|
6
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -121,5 +121,57 @@
|
|
|
121
121
|
}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
+
### 試したこと3
|
|
125
|
+
`memo` を利用してメモ化しましたが name, password どちらか1方を変更すると、どちらも再レンダリングされてしまいます。
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import { memo, useState } from 'react'
|
|
129
|
+
|
|
130
|
+
interface Props {
|
|
131
|
+
value: string
|
|
132
|
+
setValue: (value: string) => void
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function NameInput(props: Props) {
|
|
136
|
+
return (
|
|
137
|
+
<div>
|
|
138
|
+
<input name="name" value={props.value} onChange={(e) => props.setValue(e.target.value)} />
|
|
139
|
+
</div>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function PasswordInput(props: Props) {
|
|
144
|
+
return (
|
|
145
|
+
<div>
|
|
146
|
+
<input name="password" value={props.value} onChange={(e) => props.setValue(e.target.value)} />
|
|
147
|
+
</div>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const MemoNameInput = memo(NameInput)
|
|
152
|
+
const MemoPasswordInput = memo(PasswordInput)
|
|
153
|
+
|
|
154
|
+
export default function App() {
|
|
155
|
+
const [name, setName] = useState('')
|
|
156
|
+
const [password, setPassword] = useState('')
|
|
157
|
+
|
|
158
|
+
function handleSubmit(e: React.SubmitEvent<HTMLFormElement>) {
|
|
159
|
+
e.preventDefault()
|
|
160
|
+
|
|
161
|
+
console.log(`name is ${name}`)
|
|
162
|
+
console.log(`password is ${password}`)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<form onSubmit={handleSubmit}>
|
|
167
|
+
<MemoNameInput value={name} setValue={(value) => { setName(value) }} />
|
|
168
|
+
<MemoPasswordInput value={password} setValue={(value) => { setPassword(value) }} />
|
|
169
|
+
|
|
170
|
+
<input type="submit" />
|
|
171
|
+
</form>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
124
176
|
### 補足情報(FW/ツールのバージョンなど)
|
|
125
177
|
- React 19.2.4
|
5
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
handleSubmit で name, password の値が取得できていますが React として適切な書き方なのかが疑問です。
|
|
91
91
|
どちらかというと今までの古き良きHTML + JavaScriptのような書き方を彷彿とさせます。
|
|
92
92
|
|
|
93
|
-
また、useEffect であればエディタの名前変更機能を利用すれば自動的に全ての変数名が変更されますが、FormDataの場合は必ず手動でname属性と formData.get を修正
|
|
93
|
+
また、useEffect であればエディタの名前変更機能を利用すれば自動的に全ての変数名が変更されますが、FormDataの場合は必ず手動でname属性と formData.get を修正する必要があります。
|
|
94
94
|
フォームが複雑になると人為的ミスをする可能性も出てくるので避けたいです。
|
|
95
95
|
|
|
96
96
|
```tsx
|
4
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -118,10 +118,6 @@
|
|
|
118
118
|
<input type="submit" />
|
|
119
119
|
</form>
|
|
120
120
|
)
|
|
121
|
-
}s
|
|
122
|
-
<input type="submit" />
|
|
123
|
-
</form>
|
|
124
|
-
)
|
|
125
121
|
}
|
|
126
122
|
```
|
|
127
123
|
|
3
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
### 試したこと1
|
|
43
43
|
以下のように NameInput と PasswordInput に別けました。
|
|
44
|
-
コンポーネントごとの再レンダリングなので期待する結果になりました。
|
|
44
|
+
コンポーネントごとの最小限の再レンダリングなので期待する結果になりました。
|
|
45
45
|
しかし、 handleSubmit で name と password が取得できなくなりました。
|
|
46
46
|
|
|
47
47
|
```tsx
|
2
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
### 試したこと1
|
|
43
43
|
以下のように NameInput と PasswordInput に別けました。
|
|
44
|
+
コンポーネントごとの再レンダリングなので期待する結果になりました。
|
|
44
45
|
しかし、 handleSubmit で name と password が取得できなくなりました。
|
|
45
46
|
|
|
46
47
|
```tsx
|
1
a
title
CHANGED
|
File without changes
|
body
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
### 発生している問題
|
|
5
5
|
name, password どちらか1文字でも値を変更するとApp自体が再レンダリングされてしまいます。
|
|
6
6
|
|
|
7
|
+
Reactの再レンダリングが発生しているかは [React Developer Tools](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) を利用して視覚的に確認しています。
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
7
11
|
### 該当のソースコード
|
|
8
12
|
```jsx
|
|
9
13
|
import { useState } from 'react'
|