teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

テキスト追加

2021/11/28 23:59

投稿

退会済みユーザー
answer CHANGED
@@ -130,7 +130,7 @@
130
130
  }
131
131
  }
132
132
  ```
133
- 上記のクラス`Cube` は、質問にあるコードにある`class Rectangular` と同様のものです。以下はこのクラスを使った場合の修正箇所です。
133
+ 上記のクラス`Cube` は、質問に添付のコードに含まれていた`class Rectangular` と同様のものです。以下はこのクラスを使った場合の修正箇所です。
134
134
 
135
135
  ```diff
136
136
  import "./styles.css";

2

テキスト追加

2021/11/28 23:59

投稿

退会済みユーザー
answer CHANGED
@@ -130,9 +130,8 @@
130
130
  }
131
131
  }
132
132
  ```
133
+ 上記のクラス`Cube` は、質問にあるコードにある`class Rectangular` と同様のものです。以下はこのクラスを使った場合の修正箇所です。
133
134
 
134
- 以下は上記の`Cude`クラスを使った場合の修正箇所です。
135
-
136
135
  ```diff
137
136
  import "./styles.css";
138
137
  -import { useState, useEffect } from "react";

1

テキスト追加

2021/11/28 23:45

投稿

退会済みユーザー
answer CHANGED
@@ -111,4 +111,181 @@
111
111
 
112
112
  ```
113
113
 
114
- - ご質問にある codesandbox を fork して上記の修正を反映したもの ???? [20211124-tablemultiple-forked-1vh3h](https://codesandbox.io/s/20211124-tablemultiple-forked-1vh3h?file=/src/App.js)
114
+ - ご質問にある codesandbox を fork して上記の修正を反映したもの ???? [20211124-tablemultiple-forked-1vh3h](https://codesandbox.io/s/20211124-tablemultiple-forked-1vh3h?file=/src/App.js)
115
+
116
+
117
+ ### 別案
118
+
119
+ stateを見直すことは同じですが、各直方体の3辺の情報自体を、Appのstate として持つというのもありかと思います。たとえば、以下のようなクラスを作り、これのインスタンスの配列 `cubes` を stateに持たせます。
120
+ ```javascript
121
+ class Cube {
122
+ constructor(otherCube) {
123
+ this.vertical = otherCube ? otherCube.vertical : 0;
124
+ this.horizontal = otherCube ? otherCube.horizontal : 0;
125
+ this.height = otherCube ? otherCube.height : 0;
126
+ }
127
+
128
+ get volume() {
129
+ return this.vertical * this.horizontal * this.height;
130
+ }
131
+ }
132
+ ```
133
+
134
+ 以下は上記の`Cude`クラスを使った場合の修正箇所です。
135
+
136
+ ```diff
137
+ import "./styles.css";
138
+ -import { useState, useEffect } from "react";
139
+ -// import { Cube } from "./components/Cube";
140
+ +import { useState, useCallback } from "react";
141
+ +
142
+ +class Cube {
143
+ + constructor(otherCube) {
144
+ + this.vertical = otherCube ? otherCube.vertical : 0;
145
+ + this.horizontal = otherCube ? otherCube.horizontal : 0;
146
+ + this.height = otherCube ? otherCube.height : 0;
147
+ + }
148
+ +
149
+ + get volume() {
150
+ + return this.vertical * this.horizontal * this.height;
151
+ + }
152
+ +}
153
+
154
+ export default function App() {
155
+ - const [numberOfCubes, setNumberOfCubes] = useState(1);
156
+ - const [total, setTotal] = useState(0);
157
+ + const [cubes, setCubes] = useState([new Cube()]);
158
+ +
159
+ const decreaseCubes = () => {
160
+ - if (numberOfCubes === 0) return;
161
+ - setNumberOfCubes(numberOfCubes - 1);
162
+ + if (cubes.length === 0) return;
163
+ + setCubes(cubes.slice(0, cubes.length - 1));
164
+ };
165
+ +
166
+ const increaseCubes = () => {
167
+ - setNumberOfCubes(numberOfCubes + 1);
168
+ + setCubes([...cubes, new Cube()]);
169
+ };
170
+
171
+ + const handleChangeCube = useCallback(
172
+ + (selectedIndex, name, size) => {
173
+ + setCubes(
174
+ + cubes.map((cube, i) => {
175
+ + if (i === selectedIndex) {
176
+ + const newCube = new Cube(cube);
177
+ + newCube[name] = size;
178
+ + return newCube;
179
+ + }
180
+ + return cube;
181
+ + })
182
+ + );
183
+ + },
184
+ + [cubes]
185
+ + );
186
+ +
187
+ return (
188
+ <div className="App">
189
+ <table className="table-auto my-10">
190
+
191
+ ```
192
+
193
+
194
+ ```diff
195
+ </tr>
196
+ </thead>
197
+ <tbody>
198
+ - {[...(Array(numberOfCubes) || 0)].map((key) => (
199
+ - <Row key={key} />
200
+ + {cubes.map((cube, i) => (
201
+ + <Row
202
+ + key={`cube-${i}`}
203
+ + cube={cube}
204
+ + onChange={(name, size) => handleChangeCube(i, name, size)}
205
+ + />
206
+ ))}
207
+ </tbody>
208
+ <tfoot>
209
+ <tr>
210
+ <th colSpan="3">計</th>
211
+ - <td className="text-right">{total}</td>
212
+ + <td className="text-right">
213
+ + {cubes.reduce((total, cube) => total + cube.volume, 0)}
214
+ + </td>
215
+ </tr>
216
+ </tfoot>
217
+ </table>
218
+ ```
219
+
220
+
221
+ ```diff
222
+ </div>
223
+ );
224
+ }
225
+ -const Row = () => {
226
+ - const [vertical, setVertical] = useState(0);
227
+ - const [horizontal, setHorizontal] = useState(0);
228
+ - const [height, setHeight] = useState(0);
229
+ - const onChangeVertical = (event) => {
230
+ - setVertical(event.target.value);
231
+ - };
232
+ - const onChangeHorizontal = (event) => {
233
+ - setHorizontal(event.target.value);
234
+ - };
235
+ - const onChangeHeight = (event) => {
236
+ - setHeight(event.target.value);
237
+ - };
238
+ - const volume = vertical * horizontal * height;
239
+ +const Row = ({ cube, onChange }) => {
240
+ + const handleChange = useCallback(
241
+ + (name, size) => {
242
+ + onChange(name, size);
243
+ + },
244
+ + [onChange]
245
+ + );
246
+ +
247
+ return (
248
+ <tr>
249
+ - <td>
250
+ - <input
251
+ - type="number"
252
+ - value={vertical}
253
+ - onChange={onChangeVertical}
254
+ - className="rounded border-2 p-1 w-20 text-right"
255
+ - />
256
+ - </td>
257
+ - <td>
258
+ - <input
259
+ - type="number"
260
+ - value={horizontal}
261
+ - onChange={onChangeHorizontal}
262
+ - className="rounded border-2 p-1 w-20 text-right"
263
+ - />
264
+ - </td>
265
+ - <td>
266
+ - <input
267
+ - type="number"
268
+ - value={height}
269
+ - onChange={onChangeHeight}
270
+ - className="rounded border-2 p-1 w-20 text-right"
271
+ - />
272
+ - </td>
273
+ - <td className="text-right">{volume}</td>
274
+ + {["vertical", "horizontal", "height"].map((name) => (
275
+ + <td key={name}>
276
+ + <input
277
+ + type="number"
278
+ + value={cube[name]}
279
+ + onChange={(e) => handleChange(name, e.target.valueAsNumber)}
280
+ + className="rounded border-2 p-1 w-20 text-right"
281
+ + />
282
+ + </td>
283
+ + ))}
284
+ + <td className="text-right">{cube.volume}</td>
285
+ </tr>
286
+ );
287
+ // useEffect(()=>{
288
+
289
+ ```
290
+
291
+ - ご質問にある codesandbox を fork して上記の修正を反映したもの ???? [20211124-tablemultiple-forked-f3pqt](https://codesandbox.io/s/20211124-tablemultiple-forked-f3pqt?file=/src/App.js)