質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

受付中

React Hooksで値の更新が反映されない

退会済みユーザー
退会済みユーザー

総合スコア0

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

1回答

0評価

0クリップ

5553閲覧

投稿2020/03/09 12:21

前提・実現したいこと

IEX CloudのAPIを使って、シンプルな株のポートフォリオのウェブアプリケーションを作ろうとしています。
こちらのQiitaの記事を参考にさせて頂き、MATERIAL-UIを使って、テーブルのソート機能を実装しております。

発生している問題・エラーメッセージ

SortableTable.jsのSortableTable関数の中で、引数のdataをそのままconsole.logで出力しているのですが、一度目の表示で、値が更新されていないのが分かりました。どの様にすれば、React Hooksで、一度目から値を更新できるのでしょうか?
また、そもそもなぜログが無限に出てきてしまうのかも分かりません。
値の更新は、App.jsのaddStock関数で行っております。

コンソール

また、React Hooksを使って、APIから取ってきた値をどの様に保存しておけばいいのかも分かっておりません。useStateでいくつか配列を用意しておいた場合、どの様に値を追加していけばいいのでしょうか?

該当のソースコード

App.js

React

import React, { useState } from 'react'; import { makeStyles } from "@material-ui/core/styles"; import SortableTable from "./SortableTable.js"; const useStyles = makeStyles({ table: { width: "60%" } }); export default function App() { const [listOfStocks, setListOfStocks] = useState([]) const [state, setState] = useState({ symbol: [], name: [], price: [], num_shares: [], totalValue: [] }); function addStock() { const url = urlForIEXCloud("aapl") fetch(url).then((r) => r.json()).then((data) => { setState({ symbol: data.symbol, name: data.companyName, price: data.iexRealtimePrice, share: 10, totalValue: 200 }); }); } function generateTableData(numRow) { const data = [...Array(numRow).keys()].map(i => ({ "Symbol": state.symbol, "Company Name": state.name, "Real Time Price": state.price, "Number of Shares": state.share, "Total Value": state.totalValue })); return data; } const classes = useStyles(); addStock(); const data = generateTableData(1); return <SortableTable data={data} className={classes.table} />; } function urlForIEXCloud(symbol) { const base_url = "https://cloud.iexapis.com/" const version = "stable/" const endpoint_path = `stock/${symbol}/quote` const token = "pk_b56bbfd8b3d54c2c9417a27e8e35b64f" const query_string_params = `?token=${token}` return `${base_url}${version}${endpoint_path}${query_string_params}` }

SortableTable.js

import React, { useState } from "react"; import PropTypes from "prop-types"; import { makeStyles } from "@material-ui/core/styles"; import Table from "@material-ui/core/Table"; import TableHead from "@material-ui/core/TableHead"; import TableCell from "@material-ui/core/TableCell"; import TableRow from "@material-ui/core/TableRow"; import TableBody from "@material-ui/core/TableBody"; import TableSortLabel from "@material-ui/core/TableSortLabel"; import Paper from "@material-ui/core/Paper"; const useStyles = makeStyles({ root: { overflowX: "auto", whiteSpace: "nowrap" }, table: { tableLayout: "fixed" } }); export default function SortableTable({ data, className }) { console.log(data) const classes = useStyles(); const columns = Object.keys(data[0]); const [state, setState] = useState({ rows: data, order: "desc", key: columns[0] }); function handleClickSortColumn(column) { const isDesc = column === state.key && state.order === "desc"; const nextOrder = isDesc ? "asc" : "desc"; const sortRule = { asc: [1, -1], desc: [-1, 1] }; const sortedRows = state.rows.slice().sort((a, b) => { if (a[column] > b[column]) { return sortRule[nextOrder][0]; } else if (a[column] < b[column]) { return sortRule[nextOrder][1]; } else { return 0; } }); setState({ rows: sortedRows, order: nextOrder, key: column }); } return ( <div className={className}> <Paper className={classes.root}> <Table size="medium" className={classes.table}> <TableHead> <TableRow> {columns.map((column, colIndex) => ( <TableCell align={isNaN(state.rows[0][column]) ? "left" : "right"} key={`table-header-col-${colIndex}`} sortDirection={state.key === column ? state.order : false} > <TableSortLabel active={state.key === column} direction={state.order} onClick={() => handleClickSortColumn(column)} > {column} </TableSortLabel> </TableCell> ))} </TableRow> </TableHead> <TableBody> {state.rows.map((row, rowIndex) => ( <TableRow hover key={`table-row-row-${rowIndex}`}> {Object.keys(row).map((key, colIndex) => ( <TableCell align={isNaN(row[key]) ? "left" : "right"} key={`table-row-${rowIndex}-col-${colIndex}`} > {row[key]} </TableCell> ))} </TableRow> ))} </TableBody> </Table> </Paper> </div> ); } SortableTable.propTypes = { data: PropTypes.arrayOf(PropTypes.object).isRequired, className: PropTypes.string, };

補足情報(FW/ツールのバージョンなど)

よろしくお願い致します。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

hoshi-takanori
hoshi-takanori

2020/03/10 01:01

一度目の表示はまだ API から結果が帰ってきてないためで、「ロード中」みたいなのを表示するのがいいと思います。 ログが無限に出てくるのは、表示内容を更新するたびに App 関数が実行されて fetch が呼ばれるためで、API を繰り返し呼びすぎてますね。useEffect を使わないとやばいです。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。