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

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

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

Storage+は、IT業界団体CompTIA認定の資格で、ストレージに関する知識を証明します。ストレージの設計・構築~運用・管理までの知識を評価し、接続時のトラブルシューティングや基礎的なストレージ・システム管理のスキルを取得している証明になります。

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

Q&A

0回答

1452閲覧

React Native(Expo)で複数画像をFirebase StorageとFirestoreで管理する

sheckwes

総合スコア13

Storage+

Storage+は、IT業界団体CompTIA認定の資格で、ストレージに関する知識を証明します。ストレージの設計・構築~運用・管理までの知識を評価し、接続時のトラブルシューティングや基礎的なストレージ・システム管理のスキルを取得している証明になります。

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

1グッド

1クリップ

投稿2020/03/12 05:31

###実現したいこと
複数の画像をカメラロールから選択、Firebase Storageへアップロード(メルカリの出品する際の画像選択)のイメージです。

###現状
画像を1枚選んでアップロードする場合は下記のコードでできています。

流れとしては、
①画像を選択する時にonPressAdd()が始まる
②uploadPostImg()の処理でFirebase Storageへの画像のアップロード
③画像のダウンロードURLがstateに書き込まれる

items collectionのドキュメントの中のphraseというフィールドとurlというフィールドにstorageのurlが入るようになっています。

画像を5枚まで選択できるようにしたいので、

ドキュメント items
フィールド phrase, url1(1枚目の画像のurl), url2(2枚目の画像のurl), url3, url4, url5

このようにしたいです。
ご教示いただけると幸いです。

###コード

javascript

1export default class Register extends Component<Props> { 2 constructor(props) { 3 super(props); 4 this.state = { 5 imgUrl: '', 6 phrase: '', 7 addedPost: [], 8 }; 9 } 10 11 // 投稿時の処理 12 async onPressAdd() { 13 await this.uploadPostImg(); 14 const { imgUrl, phrase, postIndex } = await this.state; 15 this.uploadPost(imgUrl, phrase, postIndex); 16 this.setState( 17 { 18 addedPost: [ 19 { 20 imgUrl, 21 phrase, 22 postIndex, 23 }, 24 ], 25 } 26 ); 27 } 28 29 onAddImagePressed = async () => { 30 const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); 31 if (status === 'granted') { 32 const result = await ImagePicker.launchImageLibraryAsync({ 33 allowsEditing: true, 34 mediaTypes: ImagePicker.MediaTypeOptions.Images, 35 }); 36 if (!result.cancelled) { 37 // ImageManipulatorでリサイズ処理 38 const actions = []; 39 actions.push({ resize: { width: 350 } }); 40 const manipulatorResult = await ImageManipulator.manipulateAsync( 41 result.uri, 42 actions, 43 { 44 compress: 0.4, 45 }, 46 ); 47 this.setState({ 48 imgUrl: manipulatorResult.uri, 49 }); 50 } 51 } 52 }; 53 54 uploadPostImg = async () => { 55 const metadata = { 56 contentType: 'image/jpeg', 57 }; 58 const postIndex = Date.now().toString(); 59 const storage = firebase.storage(); 60 const imgURI = this.state.imgUrl; 61 const response = await fetch(imgURI); 62 const blob = await response.blob(); 63 const uploadRef = storage.ref('images').child(`${postIndex}`); 64 65 // storageに画像を保存 66 await uploadRef.put(blob, metadata).catch(() => { 67 alert('画像の保存に失敗しました'); 68 }); 69 70 // storageのダウンロードURLをsetStateする 71 await uploadRef 72 .getDownloadURL() 73 .then(url => { 74 this.setState({ 75 imgUrl: url, 76 postIndex, 77 }); 78 }) 79 .catch(() => { 80 alert('失敗しました'); 81 }); 82 }; 83 84 // stateに入っているダウンロードURLなどをFirestoreに記述する 85 uploadPost(url, phrase, postIndex) { 86 Fire.shared.uploadPost({ 87 url, 88 phrase, 89 postIndex, 90 }); 91 } 92 93 render() { 94 return ( 95 <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}> 96 <Container> 97 <Header> 98 <Left /> 99 <Body> 100 <Title>商品登録</Title> 101 </Body> 102 <Right /> 103 </Header> 104 <View> 105 <TouchableOpacity 106 onPress={() => this.onAddImagePressed()} 107 > 108 {this.state.imgUrl ? ( 109 <Image source={{ uri: this.state.imgUrl }} style={{ width: 100, height: 100, alignSelf: 'center' }} /> 110 ) : ( 111 <Icon 112 name="camera-retro" 113 type="font-awesome" 114 size={50} 115 color="gray" 116 /> 117 )} 118 </TouchableOpacity> 119 <Item> 120 <Input 121 placeholder='phrase' 122 autoCapitalize={'none'} 123 onChangeText={phrase=> this.setState({ phrase })} 124 required 125 onPress={Keyboard.dismiss} 126 /> 127 </Item> 128 <Button 129 title="追加" 130 onPress={() => this.onPressAdd()} 131 /> 132 </View> 133 </Container> 134 </TouchableWithoutFeedback> 135 ); 136 } 137}

###書き換えているコード(途中まで)

javascript

1export default class Register extends Component<Props> { 2 constructor(props) { 3 super(props); 4 this.state = { 5 imgUrl1: '', 6 imgUrl2: '', 7 phrase: '', 8 addedPost: [], 9 }; 10 } 11 12 // 投稿時の処理 13 async onPressAdd() { 14 await this.uploadPostImg(); 15 const { imgUrl1, imgUrl2, phrase, postIndex } = await this.state; 16 this.uploadPost(imgUrl1, imgUrl2, phrase, postIndex); 17 this.setState( 18 { 19 addedPost: [ 20 { 21 imgUrl, 22 phrase, 23 postIndex, 24 }, 25 ], 26 } 27 ); 28 } 29 30 onAddImagePressed = async () => { 31 const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); 32 if (status === 'granted') { 33 const result = await ImagePicker.launchImageLibraryAsync({ 34 allowsEditing: true, 35 mediaTypes: ImagePicker.MediaTypeOptions.Images, 36 }); 37 if (!result.cancelled) { 38 // ImageManipulatorでリサイズ処理 39 const actions = []; 40 actions.push({ resize: { width: 350 } }); 41 const manipulatorResult = await ImageManipulator.manipulateAsync( 42 result.uri, 43 actions, 44 { 45 compress: 0.4, 46 }, 47 ); 48 this.setState({ 49 imgUrl: manipulatorResult.uri, 50 }); 51 } 52 } 53 }; 54 55 uploadPostImg = async () => { 56 const metadata = { 57 contentType: 'image/jpeg', 58 }; 59 const postIndex = Date.now().toString(); 60 const storage = firebase.storage(); 61 const imgURI = this.state.imgUrl; 62 const response = await fetch(imgURI); 63 const blob = await response.blob(); 64 const uploadRef = storage.ref('images').child(`${postIndex}`); 65 66 // storageに画像を保存 67 await uploadRef.put(blob, metadata).catch(() => { 68 alert('画像の保存に失敗しました'); 69 }); 70 71 // storageのダウンロードURLをsetStateする 72 await uploadRef 73 .getDownloadURL() 74 .then(url => { 75 this.setState({ 76 imgUrl: url, 77 postIndex, 78 }); 79 }) 80 .catch(() => { 81 alert('失敗しました'); 82 }); 83 }; 84 85 // stateに入っているダウンロードURLなどをFirestoreに記述する 86 uploadPost(url, phrase, postIndex) { 87 Fire.shared.uploadPost({ 88 url1, 89 url2, 90 phrase, 91 postIndex, 92 }); 93 } 94 95 render() { 96 return ( 97 <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}> 98 <Container> 99 <Header> 100 <Left /> 101 <Body> 102 <Title>商品登録</Title> 103 </Body> 104 <Right /> 105 </Header> 106 <View> 107 <TouchableOpacity 108 onPress={() => this.onAddImagePressed()} 109 > 110 {this.state.imgUrl1 ? ( 111 <Image source={{ uri: this.state.imgUrl1 }} style={{ width: 100, height: 100, alignSelf: 'center' }} /> 112 ) : ( 113 <Icon 114 name="camera-retro" 115 type="font-awesome" 116 size={50} 117 color="gray" 118 /> 119 )} 120 </TouchableOpacity> 121 <TouchableOpacity 122 onPress={() => this.onAddImagePressed()} 123 > 124 {this.state.imgUrl2 ? ( 125 <Image source={{ uri: this.state.imgUrl2 }} style={{ width: 100, height: 100, alignSelf: 'center' }} /> 126 ) : ( 127 <Icon 128 name="camera-retro" 129 type="font-awesome" 130 size={50} 131 color="gray" 132 /> 133 )} 134 </TouchableOpacity> 135 <Item> 136 <Input 137 placeholder='phrase' 138 autoCapitalize={'none'} 139 onChangeText={phrase=> this.setState({ phrase })} 140 required 141 onPress={Keyboard.dismiss} 142 /> 143 </Item> 144 <Button 145 title="追加" 146 onPress={() => this.onPressAdd()} 147 /> 148 </View> 149 </Container> 150 </TouchableWithoutFeedback> 151 ); 152 } 153}
s.k👍を押しています

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問