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

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

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

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

JavaScript

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

React.js

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

Q&A

解決済

2回答

441閲覧

React 仮想DOMにおける配列の再レンダリング

van-0215

総合スコア89

React Native

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

JavaScript

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

React.js

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

0グッド

1クリップ

投稿2018/12/14 04:43

現在 ReactNative を使って、アプリを作っています。

オブジェクトの配列にあるユーザー情報を map()を用いて描画しています。

<スクリーン>

javascript

1//初期化 2constructor(props) { 3 super(props); 4 this.state = ({ 5 userList: [ 6 { id: 1, iconUri: "https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg", userName: 'Momoka', followStatus: true }, 7 { id: 2, iconUri: "https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg", userName: 'Tinatsu', followStatus: false }, 8 { id: 3, iconUri: "https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg", userName: 'Nakagawa', followStatus: true }, 9 { id: 4, iconUri: "https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg", userName: 'Haruna', followStatus: true }, 10 ], 11 }); 12 this.handleFollowChange = this.handleFollowChange.bind(this); 13} 14 15// フォローボタン機能 16handleFollowChange(key) { 17 tmpUserList = this.state.userList; 18 tmpUserList[key].followStatus = !(tmpUserList[key].followStatus); 19 this.setState({ userList: tmpUserList }); 20}; 21 22//レンダリング 23render () { 24{this.state.userList.map((item, key) => { 25 if (item.followStatus) { 26 buttonColor = '#0088FF'; 27 buttonText = 'フォロー'; 28 } else { 29 buttonColor = '#2244AA'; 30 buttonText = '解除'; 31 } 32 console.log(item.followStatus); 33 return ( 34 <View key={item.id}> 35 <UserContainer 36 userName={item.userName} 37 userIcon={item.iconUri} 38 associated={"follow"} 39 handleFollowChange={() => this.handleFollowChange(key)} 40 buttonColor={buttonColor} 41 buttonText={buttonText} 42 /> 43 </View> 44 ); 45 })} 46}

<UserContainerコンポーネント>

javascript

1constructor(props) { 2 super(props); 3 this.state = { 4 userName: this.props.userName, 5 userIcon: this.props.userIcon, 6 associated: this.props.associated, 7 buttonColor: this.props.buttonColor, 8 buttonText: this.props.buttonText, 9 handleFollowChange: this.props.handleFollowChange, 10 }; 11} 12render() { 13 // console.log(this.state.userName) 14 return ( 15 <View> 16 <TouchableOpacity 17 style={[UserContainerStyle.userContainer, { borderWidth: 1, borderColor: '#888', }]} 18 onPress={() => Actions.profile()} 19 > 20 <Avatar 21 containerStyle={UserContainerStyle.userAvatar} 22 size={40} 23 rounded 24 source={{ uri: this.state.userIcon }} 25 activeOpacity={0.7} 26 /> 27 <Text style={UserContainerStyle.UserName}>{this.state.userName}</Text> 28 {(() => { 29 /* フォローボタンが必要なユーザーコンテナ */ 30 if (this.state.associated === "follow") { 31 console.log(this.state); 32 return ( 33 <View> 34 <Button 35 title={this.state.buttonText} 36 onPress={this.state.handleFollowChange} 37 containerViewStyle={UserContainerStyle.FollowButton} 38 buttonStyle={{ backgroundColor: this.state.buttonColor }} 39 /> 40 </View> 41 ); 42 } else { 43 return ( 44 <View> 45 </View> 46 ); 47 } 48 })()} 49 </TouchableOpacity> 50 </View> 51 ); 52 }

UserContainerにある、フォローボタンを押した際に、 「テキスト」と「カラー」が変わることを想定して書いております。(イメージはツイッターのフォローボタン)

しかしながら、仮想DOMの特性上、UserContainer自体は外から見て、変わっているようには見えないので、ボタンの 「テキスト」と「カラー」が変化してくれません。

どうしたら、変える事ができるのでしょうか? 皆様のお知恵をお借りしたいです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

考えられることとして、this.state.userListの中身を破壊的に変更していることがあります。Reactはオブジェクトの変化で再描画するか見る部分もあるので、破壊的に変更するとうまく反映されないことがあります。

javascript

1handleFollowChange(key) { 2 // まず、配列をコピー 3 tmpUserList = this.state.userList.concat(); 4 // 中身のオブジェクトも作り直し 5 const followStatus = !tmpUserList[key].followStatus; 6 tmpUserList[key] = { ...tmpUserList[key], followStatus }; 7 this.setState({ userList: tmpUserList }); 8};

投稿2018/12/14 04:55

maisumakun

総合スコア145123

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

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

van-0215

2018/12/14 08:10

やりましたが、変更されませんでした。
maisumakun

2018/12/14 08:15 編集

配列から展開した場合、keyが同じだと「そのまま同じ」とみなされてしまう、という方の都合かもしれません。 「名前とアイコンとfollowStatusをつないだ文字列」をkeyにするなどで、keyだけで完全に状態を表してしまうのも1つの手段かもしれません。
Meganezaru

2018/12/14 08:51

<UserContainer />にも、keyプロパティ、必要じゃないですかね??
van-0215

2018/12/14 09:22

お二方、ありがとうございます!できました。
guest

0

スクリーン側のmapの外側を <View key={new Date}> </View> で囲み、無理やりオブジェクトIDを変えたら、ボタンは変更できた。
ただ、やり方としてナンセンスな気がします。ご回答をお待ちしています。

投稿2018/12/14 04:51

van-0215

総合スコア89

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問