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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

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

Q&A

解決済

1回答

2420閲覧

React readAsDataURLメソッドを使ってbase64形式にエンコードされたURLを配列に入れたい

pokerStars

総合スコア67

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

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

0グッド

0クリップ

投稿2020/06/13 08:40

編集2020/06/14 03:51

React

1import React from 'react' 2export default class ProductList extends React.Component { 3constructor(props) { 4 super(props) 5 this.state ={ 6 file: "", 7 imagePreviewUrl: "" 8 } 9 } 10 11handleFileChange = (id,e) => { 12 e.preventDefault() 13 const products = this.props.products; 14 let reader = new FileReader() 15 let file = e.target.files[0] 16 reader.onloadend = () => { 17 this.setState({ 18 file: file, 19 imagePreviewUrl: reader.result 20 }); 21 } 22 reader.readAsDataURL(file) 23 this.props.file(id, ??? )// ???の部分を色々試してみたがどれも期待値にならない 24// 試したこと reader,reader.result,this.state.imagePreviewUrlを???に入れてみた 25 26 } 27 28} 29 30render() { 31const product = this.props.products.map((product) => { 32 if (product.isVisible === true ){ 33 return( 34 <ul key={product.id}> 35 <li>{product.title}</li> 36 <li>{product.desc}</li> 37 <li>{product.price}</li> 38 <div> 39 <button type="submit" onClick={() => this.delete(product.id)}>削除</button> 40 <button type="submit" onClick = {(e) => this.handleButton(product.id , e)}>編集</button> 41 </div> 42 43 <div> 44 <input type="file" onChange={(e) => this.handleFileChange(product.id, e)}/> 45 <img src={this.state.imagePreviewUrl} /> 46 </div> 47 48 {product.editIsVisible && 49 <EditForm 50 product = {this.props.products} 51 edit = {this.edit} 52 id = {product.id} 53 />} 54 </ul> 55 ) 56 } 57 }); 58 const searchItem = this.props.products.filter( function( value ) { 59 return value.isVisible === true 60 }) 61 62 return ( 63 <div> 64 <h1>商品リスト</h1> 65 {product} 66 <h3>商品件数は{searchItem.length}件です</h3> 67 </div> 68 ) 69 }

React

1import React from 'react' 2 3export default class ProductContainer extends React.Component { 4 constructor(props) { 5 super(props) 6 this.state = { 7 products: [] 8 } 9 } 10 11add = (title, desc, price) => { 12 const newProducts = this.state.products 13 const product = { 14 id: newProducts.length + 1, 15 title: title, 16 desc: desc, 17 price: price, 18 fileName: "" } 19 newProducts.push(product) 20 this.setState({products: newProducts}) 21 } 22 23//fileName = reader.readAsDataURL(file)でbase64形式にエンコードされたURL 24file = (id,fileName) => { 25 const products = this.state.products; 26 //画像を表示したい配列を取得 27 const fileIndex = products.findIndex( product => product.id === id ) ; 28//(例)"data:image/jpeg;base64,/9j/... をfileNameに上書き保存したい 29 products[fileIndex].fileName = fileName 30 this.setState({products: products}) 31 } 32 33 34render() { 35 36 return ( 37 <div> 38 <ProductForm add={this.add} /> 39 <ProductList 40 products={this.state.products} 41 file = {this.file} 42 /> 43 </div> 44 45 46 ) 47 }

イメージ説明

・現在の問題は下記のように一つの画像を変更すると全ての画像が変更されて表示されてしまうことです。
イメージ説明

・期待値としては配列ごとに違う画像を表示させるようにしたいです。

足りない情報や、試してほしい情報は遠慮なくお申し付けください!
お力をいただきたいです。

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

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

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

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

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

hoshi-takanori

2020/06/13 23:57

imagePreviewUrl を products の各要素に持たせればいいと思いますが、ProductList と ProductContainer の関係がよく分かりません。
pokerStars

2020/06/14 04:01

ご返信ありがとうございます。 ProductContainerに商品の一覧や、追加フォーム、編集フォームなどの機能を表示できるようなものにしています。 ProductListは商品の配列を一つずつに編集ボタンや削除ボタンなど、配列の中身をいじれるような機能にしています。 上記のコードにも少しだけ補足させていただきました! 自分もimagePreviewUrl を products の各要素に持たせれば表示できると考えているのですが、FileReaderのresultを取得できないのです。 コンソールではFileReaderのresultが ""と空白になっている部分とdate;image...となっている部分があるのですがなぜそのような値の中身の違いが発生しているのかも分からないです汗
guest

回答1

0

ベストアンサー

いろいろ突っ込みどころはありますが、とりあえず以下の修正で動くのでは。

ProductList

  • reader.onloadend で this.props.file を呼ぶ。引数に base64 形式でエンコードされた URL を追加。
  • 画像の表示は各 product の imagePreviewUrl を使う。
  • このコンポーネントには state は不要。

diff

1 handleFileChange = (id,e) => { 2 e.preventDefault() 3 const products = this.props.products; 4 let reader = new FileReader() 5 let file = e.target.files[0] 6 reader.onloadend = () => { 7- this.setState({ 8- file: file, 9- imagePreviewUrl: reader.result 10- }); 11+ this.props.file(id, file, reader.result); 12 } 13 reader.readAsDataURL(file) 14- this.props.file(id, ??? )// ???の部分を色々試してみたがどれも期待値にならない 15 // 試したこと reader,reader.result,this.state.imagePreviewUrlを???に入れてみた 16 17 } 18 19 render() { 20 const product = this.props.products.map((product) => { 21 // 略 22 23 <div> 24 <input type="file" onChange={(e) => this.handleFileChange(product.id, e)}/> 25- <img src={this.state.imagePreviewUrl} /> 26+ <img src={product.imagePreviewUrl} /> 27 </div>

ProductContainer

  • file メソッドに imagePreviewUrl 引数を追加。
  • setState の際には、配列は作り直す必要があるので、引数なしの slice メソッドでコピー。
  • setState の際には、オブジェクトも作り直す必要があるので、スプレッド構文を利用。

diff

1 add = (title, desc, price) => { 2- const newProducts = this.state.products 3+ const newProducts = this.state.products.slice() 4 const product = { 5 // 略 6 } 7 8 //fileName = reader.readAsDataURL(file)でbase64形式にエンコードされたURL 9-file = (id,fileName) => { 10- const products = this.state.products; 11+file = (id, fileName, imagePreviewUrl) => { 12+ const products = this.state.products.slice(); 13 //画像を表示したい配列を取得 14 const fileIndex = products.findIndex( product => product.id === id ) ; 15 //(例)"data:image/jpeg;base64,/9j/... をfileNameに上書き保存したい 16- products[fileIndex].fileName = fileName 17+ products[fileIndex] = { ...products[fileIndex], fileName, imagePreviewUrl } 18 this.setState({products: products}) 19 }

参考: JavaScriptで配列のコピー(値渡し) - Qiita
参考: オブジェクトのspread構文でのマージ - オブジェクト · JavaScript Primer #jsprimer

投稿2020/06/14 05:29

編集2020/06/14 05:31
hoshi-takanori

総合スコア7895

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

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

pokerStars

2020/06/14 05:54

誠にありがとうございます!期待値の通りに動かすことができました! なぜ動くようになったのかは今から学習していきたいと思います>< 感謝いたします!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問