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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

React.js

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

Q&A

解決済

1回答

4315閲覧

ReactでsetStateした後、再レンダリングが発生しない

YKita

総合スコア2

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

React.js

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

0グッド

0クリップ

投稿2021/10/05 10:35

前提・実現したいこと

Laravel + React(16.14.0)を使用しています。
axiosによるデータ取得後、リストとして表示する実装中に以下のエラーメッセージが発生しました。

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

axiosで取得したデータをsetStateでstate更新した後、(おそらく)再レンダリングが起きていない。 その結果、画面にデータが表示されない。

該当のソースコード

親コンポーネント

react

1import React, { useState, useEffect } from 'react'; 2import axios from 'axios'; 3import ReactDOM from 'react-dom'; 4import { Button, Container } from '@material-ui/core'; 5import AccountList from '../components/AccountList'; 6import CreateAccountForm from '../components/CreateAccountForm'; 7import Loading from './Loading' 8 9const Dashboard = () => { 10 const [officialAccounts, setOfficialAccounts] = useState([]); 11 const [loading, setLoading] = useState(true); 12 13 useEffect(() => { 14 getOfficialAccountsData(); 15 }, []) 16 17 const getOfficialAccountsData = () => { 18 axios 19 .get('/api/official_accounts') 20 .then(response => { 21 var newOfficialAccounts = [...response.data]; 22 setOfficialAccounts(newOfficialAccounts); 23 console.log(response.data); 24 setLoading(false); 25 }) 26 .catch(() => { 27 console.log('通信に失敗しました'); 28 }); 29 } 30 31 if (loading) { 32 return ( 33 <Loading /> 34 ); 35 } 36 37 return ( 38 <Container> 39 <div className="card"> 40 <div className="card-header">公式アカウント管理</div> 41 <div className="card-body"> 42 <CreateAccountForm 43 officialAccounts={officialAccounts} 44 setOfficialAccounts={setOfficialAccounts} 45 /> 46 <AccountList 47 officialAccounts={officialAccounts} 48 /> 49 </div> 50 <Button color="secondary" variant="outlined">Logout</Button> 51 </div> 52 </Container> 53 ); 54} 55 56export default Dashboard;

子コンポーネント

import React from 'react'; import ReactDOM from 'react-dom'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; import ListItemText from '@material-ui/core/ListItemText'; import IconButton from '@material-ui/core/IconButton'; import SettingsIcon from '@material-ui/icons/Settings'; import Paper from '@material-ui/core/Paper'; import green from '@material-ui/core/colors/green'; import { makeStyles, createStyles } from '@material-ui/core/styles'; import { useHistory } from 'react-router-dom'; const useStyles = makeStyles((theme) => createStyles({ })); function AccountList(props) { const classes = useStyles(); const { officialAccounts } = props; const history = useHistory(); return ( <List> {officialAccounts.map((officialAccount, index) => { <ListItem button key={index} onClick={() => history.push('user_list/' + officialAccount.id)} > <ListItemText primary={officialAccount.name} secondary={officialAccount.permission_name} /> <ListItemSecondaryAction> <IconButton disabled={!officialAccount.pivot.permission_id} type="submit" onClick={() => history.push('official_account_manage/' + officialAccount.id)} > <SettingsIcon /> </IconButton> </ListItemSecondaryAction> </ListItem> })} </List> ); } export default AccountList;

試したこと

ちなみに、現状の理解は、
①初回レンダリング時にuseEffectが実行され、stateが空配列から変更される
②stateの変更に伴い、子コンポーネントに渡すpropsの値が変化するため、子コンポーネントで再レンダリングがおこる
③officialAccountsの情報がlistコンポーネントに表示される
というプロセスなのですが、この理解で合っていますでしょうか?

ちなみに、検証ツールでみたところ、Listと対応するul はありました。中身のlistitemにあたるliがありません。
つまり、officialAccountsが空の状態のままであり、関数コンポーネントが再呼び出しされていないということになると思います。

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/10/05 11:10

console.log(response.data); で何が表示されてますか?
YKita

2021/10/05 11:21

{ access_token: "hogehoge" channel_id: "hogehoge" channel_secret: "hogehoge" created_at: "2021-09-23 00:09:14" id: 6 name: "hogehoge" permission_name: "管理者" pivot: { official_account_id: 6 official_account_permission: {id: 1, name: '管理者', created_at: null, updated_at: null} permission_id: 1 user_id: 1} [[Prototype]]: Object updated_at: "2021-09-23 00:09:14" webhook_url: "" } が要素の配列が表示されています。(access_tokenなどの中身は個人情報のため変更しています)
maisumakun

2021/10/05 11:46 編集

> つまり、officialAccountsが空の状態のままであり、関数コンポーネントが再呼び出しされていないということになると思います。 こちらの仮説を裏付ける検証は行ってみましたか?
YKita

2021/10/05 11:54

maisumakunさん 1. officialAccountsが空の状態のままであるかどうか useEffectにおいて、第二引数に[loading]を指定して関数コンポーネントを再呼び出ししました。その際、2回目のconsole.log(officialAccounts)には、上記response.dataと同じデータが入っていました。そのため、state更新自体は問題なくできていると考えています。 一方、useEffectの第二引数を空配列にした状態で, console.log(response.data); console.log(officialAccounts); を行うと、officialAccountsでは初期値である空配列が表示されています。 2. 関数コンポーネントが再呼び出しされていない に関して これは根拠のない予想です。setOfficialAccountによるstate変更が起きると、関数の再呼び出しがされて再描画がおこると考えています。そのため、再呼び出しが起きていないがために、再描画がされていないのではないかと考えました。
guest

回答1

0

ベストアンサー

原因は、おそらく全く別です。

jsx

1 return ( 2 <List> 3 {officialAccounts.map((officialAccount, index) => { 4 <ListItem 5 button 6 key={index} 7 onClick={() => history.push('user_list/' + officialAccount.id)} 8 > 9 <ListItemText 10 primary={officialAccount.name} 11 secondary={officialAccount.permission_name} 12 /> 13 <ListItemSecondaryAction> 14 <IconButton 15 disabled={!officialAccount.pivot.permission_id} 16 type="submit" 17 onClick={() => history.push('official_account_manage/' + officialAccount.id)} 18 > 19 <SettingsIcon /> 20 </IconButton> 21 </ListItemSecondaryAction> 22 </ListItem> 23 })} 24 </List> 25 );

mapが取るアロー関数が値を返さないので、officialAccountsの中身があろうがなかろうが何も描画しません。

=>のあとのカッコを丸括弧にするか、中カッコの中からreturnでJSXを返すようにしてください。

投稿2021/10/05 11:51

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/10/05 11:54

本当に再レンダリングが発生していないのだったら、<Loading />が残り続けるはずです。
YKita

2021/10/05 11:58

おっしゃる通りですね... 完全に見落としていました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問