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

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

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

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

Q&A

解決済

1回答

503閲覧

ReactでJsonファイルの特定の値によって、背景画像を切り替えたい

yamayama0812

総合スコア2

React.js

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

0グッド

1クリップ

投稿2023/01/19 10:56

編集2023/01/19 11:00

前提

ReactでJsonファイルを読み込んで、Jsonファイルにある「type」の値によって背景画像を切り替えたいと思っています。
背景画像は青いアイコン、赤いアイコン、オレンジのアイコンなど複数あるイメージです。

背景画像はコンポネートファイルに読み込んで、それをstyle属性に設定しようと考えています。

実現したいこと

Jsonファイルのある「type」の内容によって条件分岐でstyle属性に設定する背景画像を変更したい。
よく三項演算子などで、切り替えたりしますが条件が複数の場合の方法が知りたいです。

ファイル構成は下記です。

dummy.json
App.js
SecondBlock.js

jsonファイルを読み込んでSecondBlock.jsのコンポーネントで背景画像を切り替えたいと思っています。

該当のソースコード

JSONファイルあくまでダミーです。

json:dummy.json

1{ 2 "dummy": [ 3 4 { 5 "type":"red", 6 "tracknumber":7, 7 "time": "17:00", 8 "homenumber":6, 9 "congestion":[ 10 {"num":5,"icon":1,"cool":false}, 11 {"num":15,"icon":2,"cool":false}, 12 {"num":20,"icon":3,"cool":true}, 13 {"num":10,"icon":2,"cool":false}, 14 {"num":4,"icon":1,"cool":false}, 15 {"num":8,"icon":1,"cool":true}, 16 {"num":14,"icon":2,"cool":false}, 17 {"num":14,"icon":2,"cool":true}, 18 {"num":14,"icon":2,"cool":true}, 19 {"num":14,"icon":2,"cool":false}, 20 {"num":14,"icon":2,"cool":false} 21 ] 22 }, 23 { 24 "type":"blue", 25 "tracknumber":4, 26 "homenumber":7, 27 "congestion":[] 28 }, 29{ 30 "type":"orange", 31 "tracknumber":4, 32 "homenumber":7, 33 "congestion":[] 34 } 35 ] 36 }

`

javascript

1 2import React, { useEffect, useState } from "react"; 3import SecondBlcok from '../components/SecondBlock' 4 5const App= () => { 6 7 const [jsonData,setJsonData]=useState([]) 8 9 const fetchData = async () => { 10 try { 11 const res = await fetch(`${process.env.PUBLIC_URL}/dummy.json`); 12 const data = await res.json() 13 14 setJsonData(data.dummy) 15 16 } catch (error) { 17 console.log("error", error); 18 } 19 } 20 21 useEffect(() => { 22 fetchData () 23 }, []) 24 25 return ( 26 <div className='bg-[#5582c3]'> 27 <div className="mt-[11vw] p-[2vw]"> 28 29 {jsonData.map((data,idx)=>{ 30 const info = { 31 type:data.type, 32 tracknumber:data.tracknumber, 33 time:data.time, 34 homenumber:data.homenumber, 35 congestion:data.congestion 36 } 37 38 return( 39 <div key={idx}> 40 <SecondBlcok info={info}> 41 <ThirdBlock /> 42 </SecondBlcok> 43 </div> 44 ) 45 46 })} 47 48 </div> 49 </div> 50 51 ); 52}; 53 54export default App; 55

下記がコンポーネントとして読み込むファイルです。

javascript:SecondBlock

1 2import React from 'react' 3 4 const bgIconBlue = { 5 'background': `url(/images/bg_st-blue.jpg) 0 0 no-repeat`, 6 'backgroundSize': "contain" 7 } 8 9 const bgIconOrange = { 10 'background': `url(/images/bg_st-orange.jpg) 0 0 no-repeat`, 11 'backgroundSize': "contain" 12 } 13 14 const bgIconRed = { 15 'background': `url(/images/bg_st-red.jpg) 0 0 no-repeat`, 16 'backgroundSize': "contain" 17 } 18 19const SecondBlock = ({info,children}) => { 20 const {type,destination,tracknumber,time,homenumber}=info 21 22 23 return ( 24 <div className="text-center bg-white"> 25 <div style={} className="p-[2vw_2vw_0_8vw]"> 26 <p>ここは省略</p> 27 </div> 28 {/* 3nd accordino */} 29 {children} 30 </div> 31 ) 32} 33 34export default SecondBlock

試したこと

SecondBlock.jsのコンポーネントファイルにて。
まず条件分岐などなく、ふつうに設定すれば背景画像は表示されます。

下記、該当部分以外は省略しています。

javascript:SecondBlock.js

1 const bgIconBlue = { 2 'background': `url(/images/bg_st-blue.jpg) 0 0 no-repeat`, 3 'backgroundSize': "contain" 4 } 5 6 7return ( 8 <div className="text-center bg-white"> 9 <div style={bgIconBlue } className="p-[2vw_2vw_0_8vw]"> 10 <p>ここは省略</p> 11 </div> 12 {/* 3nd accordino */} 13 {children} 14 </div> 15 )

しかし、三項演算子だとエラーがでます。

javascript:SecondBlock.js

1 2import React from 'react' 3 4 const bgIconBlue = { 5 'background': `url(/images/bg_st-blue.jpg) 0 0 no-repeat`, 6 'backgroundSize': "contain" 7 } 8 9 const bgIconOrange = { 10 'background': `url(/images/bg_st-orange.jpg) 0 0 no-repeat`, 11 'backgroundSize': "contain" 12 } 13 14 const bgIconRed = { 15 'background': `url(/images/bg_st-red.jpg) 0 0 no-repeat`, 16 'backgroundSize': "contain" 17 } 18 19const SecondBlock = ({info,children}) => { 20 const {type,destination,tracknumber,time,homenumber}=info 21 22 23 return ( 24 <div className="text-center bg-white"> 25 <div style={`${type? bgIconBlue : bgIconRed }`} className="p-[2vw_2vw_0_8vw]"> 26 <p>ここは省略</p> 27 </div> 28 {/* 3nd accordino */} 29 {children} 30 </div> 31 ) 32} 33 34export default SecondBlock 35

上記のように「type」による三項演算子でやってみましたが、エラーがでますが、JSXにhtmlのようなスタイルの当て方がNGだと思います。

txt

1react-dom.development.js:2963 Uncaught Error: The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.

上記のように3つ以上の条件で背景画像を変更したいのですがどうすればいいのでしょうか?
ご教授いただけると助かります。

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

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

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

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

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

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

hoshi-takanori

2023/01/19 11:49

三項演算子を使うなら、style の値は文字列ではなくオブジェクトなので、 style={type ? bgIconBlue : bgIconRed} でいいはず。 そして、3つ以上になる場合は、無理やり書けないこともないけど、return の前でいったん変数に入れた方がわかりやすいと思います。
yamayama0812

2023/01/19 11:57

ご回答ありがとうございます。 書き方が間違えてましましたね。。すみません。 やはり3つ以上だとreturnの前に普通にif文などで条件分岐で変数に入れたほうが良いんですね。 Reactが初めてなので、いわゆる「こうしたほういい」みたいな方法があるのかと思いまして。 ちょっと試してみます。ありがとうございます。
yamayama0812

2023/01/20 03:45

hoshi-takanori 様 こちら試した結果ですが、希望通り表示されました。 ありがとうございます。
guest

回答1

0

自己解決

こちらアドバイスをもとに下記のように実装しました。
SecondBlock.js内でもいいのですが、最初にJsonを読み込んでmap関数ないでif文の条件分岐でアイコンを変数に入れています。
そのあとにinfoのオブジェクトに変数アイコンを追加してそれをSecondBlock.jsにprops経由で渡しています。

javascript

1 2import React, { useEffect, useState } from "react"; 3import SecondBlcok from '../components/SecondBlock' 4 5 6const bgIconBlue = { 7 'background': `url(/images/bg_st-blue.jpg) 0 0 no-repeat`, 8 'backgroundSize': "contain" 9} 10 11const bgIconOrange = { 12 'background': `url(/images/bg_st-orange.jpg) 0 0 no-repeat`, 13 'backgroundSize': "contain" 14} 15 16const bgIconRed = { 17 'background': `url(/images/bg_st-red.jpg) 0 0 no-repeat`, 18 'backgroundSize': "contain" 19} 20 21 22const App= () => { 23 24 const [jsonData,setJsonData]=useState([]) 25 26 const fetchData = async () => { 27 try { 28 const res = await fetch(`${process.env.PUBLIC_URL}/dummy.json`); 29 const data = await res.json() 30 31 setJsonData(data.dummy) 32 33 } catch (error) { 34 console.log("error", error); 35 } 36 } 37 38 useEffect(() => { 39 fetchData () 40 }, []) 41 42 return ( 43 <div className='bg-[#5582c3]'> 44 <div className="mt-[11vw] p-[2vw]"> 45 46 {jsonData.map((data,idx)=>{ 47 48 let icon={} 49 if(data.type==="blue"){ 50 icon=bgIconBlue 51 52 }else if(data.type==="red"){ 53 icon=bgIconRed 54 }else if(data.type==="orange"){ 55 icon=bgIconOrange 56 } 57 58 const info = { 59 type:data.type, 60 tracknumber:data.tracknumber, 61 time:data.time, 62 homenumber:data.homenumber, 63 congestion:data.congestion, 64 icon:icon 65 } 66 67 return( 68 <div key={idx}> 69 <SecondBlcok info={info}> 70 <ThirdBlock /> 71 </SecondBlcok> 72 </div> 73 ) 74 75 })} 76 77 </div> 78 </div> 79 80 ); 81}; 82 83export default App;

コンポーネントの引数からiconを取り出してstyle属性に設定。

javascript:SecondBlock.js

1import React from 'react' 2 3const SecondBlock = ({info,children}) => { 4 const {icon,destination,tracknumber,time,homenumber}=info 5 6 return ( 7 <div className="text-center bg-white"> 8 <div style={icon} className="p-[2vw_2vw_0_8vw]"> 9 <p>ここは省略</p> 10 </div> 11 {/* 3nd accordino */} 12 {children} 13 </div> 14 ) 15} 16 17export default SecondBlock

上記の処理で解決できました。

投稿2023/01/20 03:48

yamayama0812

総合スコア2

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問