2017-07-13 11 views
0

私は現在、ボタンとして生成するオブジェクトの配列を持っています。クリックすると、ユーザーが色を変更するためにクリックする特定のボタンの背景色が必要になります(スイッチのようにトグルして、非同期ストレージに保存することができます)。ユーザーがクリックすると、すべてのボタンの色が変わります。私は、どのようにthis.setStateをselectMetric関数で処理すべきかについてはあまりよく分かりません。これらのボタンの状態を変えることができるものですので、配列内の特定のインデックスの状態を設定するにはReact Native

class IssueSelectionScreen extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     data: cloneDeep(RISK_DATA), 
    }; 
    } 

    selectMetric = (index) => { 
    const tempData = cloneDeep(this.state.data); 
    tempData[index].flag = !tempData[index].flag; 
    this.setState({ data: tempData }); 
    } 

    showMetric() { 
    return this.state.data.map((metric, index) => { 
     // same 
    }) 
    } 

    render() { 
    // same 
    } 
} 

それは状態にボタンの配列全体を置く含まれます

import React, {Component} from 'react'; 
import {View, Text, ScrollView} from 'react-native'; 
import {Button} from 'react-native-elements'; 

const RISK_DATA = [ 
    {id: 1, text: 'cats', flag: false, buttonColor: null}, 
    {id: 2, text: 'dogs', flag: false, buttonColor: null}, 

] 


class IssueSelectionScreen extends Component { 

    state = {flag: false, buttonColor: null} 

    selectMetric = (index) => { 

    for (let i=0; i < RISK_DATA.length; i++) { 

     if (index === (RISK_DATA[i].id - 1)) { 

     console.log("RISK_DATA:", RISK_DATA[i]); // logs matching id 

// ------------------------------------------------------ 
// Problem setting correct state here: 

     RISK_DATA[i].buttonColor = this.setState({flag: true, buttonColor: '#03A9F4'}) 

     // this.setState({flag: true, buttonColor: '#03A9F4'}) 
     // this.setState({update(this.state.buttonColor[i], {buttonColor: {$set: '#03A9F4'}}) }) 


// ---------------------------------------------------------- 
     } 
    } 
    } 

    showMetric() { 
    return RISK_DATA.map((metric, index) => { 
     return (
     <View key={metric.id}> 
      <Button 
      raised 
      color={'black'} 
      title={metric.text} 
      borderRadius={12} 
      onPress={() => this.selectMetric(index)} 
      backgroundColor={this.state.buttonColor} 
      > 
      {metric.text} 
      </Button> 
      <Text>{/* intentionally blank*/} </Text> 
     </View> 
    ) 
    }) 
    } 

    render() { 
    return(
     <ScrollView style={styles.wrapper}> 
     <View style={styles.issues}> 
      {this.showMetric()} 
     </View> 
     </ScrollView> 
    ); 
    } 
} 


const styles = { 
    issues: { 
    justifyContent: 'center', 
    flexDirection: 'row', 
    flexWrap: 'wrap', 
    alignItems: 'flex-start', 
    marginTop: 10, 
    justifyContent: 'space-between', 
    }, 
    wrapper: { 
    backgroundColor: '#009688' 
    } 
} 

export default IssueSelectionScreen; 

答えて

0

ので、あなたの質問への短い答えは次のようになります。また、フラグを状態の配列として保持し、ボタン情報を別の定数として保持することもできます

このソリューションは、コードのオブジェクトの状態を変更するのを防ぐためにcloneDeep(lodashから)を使用しますが、 this.state.data.mapで新しいオブジェクトを作成します(オブジェクトが深くネストされていない限り機能します)。

Reduxを使用している場合は、リストがコンポーネントとしてプロップとして入ってきて、selectMetricがReduxのフラグを更新するアクションをディスパッチします。

+0

ありがとう、Garrett、本当に便利です! – whosbuddy

+0

私はそれがデータセット(20+)でうまくスケールされていないことに気付きました。色を変えるとき、ボタンに約1秒の遅れがあります。このコンポーネントのスケーラビリティに関するヒント – whosbuddy

+0

ArrayのScrollView/mapの代わりにFlatListを試してみました。配列上でマップを作成すると、すべての変更がすべてレンダリングされます。 FlatListには、不要なレンダリングを防ぐための最適化機能があります。 –

0

この投稿を閲覧している他の人には、上記の回答が非常に役に立ちます。それ以外の場合は点灯し、ボタンを取得しようとしている場合、いくつかの最後にコメントを追加するには、私はselectMetricにシンプルを追加しました:

if (tempData[index].flag) { 
    tempData[index].buttonColor = '#03A9F4'; 
    console.log('tempData true:', tempData); 
} else { 
    tempData[index].buttonColor = null; 
    console.log('tempData false:', tempData); 
} 

としてshowMetricでボタン上のbackgroundColorプロパティを更新:

backgroundColor={this.state.data[index].buttonColor} 
関連する問題