2016-06-23 9 views
0

のための私のSearchViewリアクト - ネイティブ - 動的な状態をJSONからちょっとそこ:)私は問題以下しまったスイッチ

にフィルタモーダルを追加することによって、私はいくつかのイベントを挙げることができるSearchPageを構築しました。これはすべてかなりうまくいく。今私はSearchPagefilterを追加しようとしています。

私がスイッチのスイッチ値を変更しようとすると、値の状態が設定されていないため、ルートに戻ります

手順私が説明した:

私はすべての私のfilterが記載されていると私はSwitchを使用してtrue/falseを設定することができているModalビューを開くしようとしています。私の考えはそれのためにJSONを作成することによって、すべてのfilter Settingsを取得することでした:

module.exports = { 
 
    "filter": 
 
     { 
 
      "track": [ 
 
       { 
 
        "id": 1, 
 
        "description": "IoT & Living tomorrow" 
 
       }, 
 
       { 
 
        "id": 2, 
 
        "description": "Smart & Digital Retail" 
 
       }, 
 
       { 
 
        "id": 3, 
 
        "description": "Startups, Digital Culture & Collaboration" 
 
       } 
 
      ] 
 
     } 
 
    }

上記JSONはちょうどexpampleのためである - 通常はそのはるかに大きいとちょうどを追跡するよりも多くの話題を持っています

JSONをインポートし、var filterに保存します。私は、データがここに適切なフォーマットである確認 - 今私はfilter Modal

import React, {Component} from 'react'; 
 
import { 
 
    ListView, 
 
    Modal, 
 
    StatusBar, 
 
    StyleSheet, 
 
    Text, 
 
    TouchableOpacity, 
 
    View, 
 
    Switch 
 
} from 'react-native'; 
 

 
var filter = require('../JSON/filter'); 
 

 
class PopoverFilter extends Component { 
 

 
    constructor(props) { 
 
     super(); 
 
     // ds for the menu entries 
 
     var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); 
 
     this.state = { 
 
      eventTracks: ds.cloneWithRows(filter.filter.track) 
 
     } 
 
     this.show = this.show.bind(this); 
 
    } 
 

 
    render() { 
 
     return(
 
      <Modal> 
 
         <ListView 
 
           style={styles.mainView} 
 
           renderRow={this.renderMenuEntries.bind(this)} 
 
           dataSource={this.state.eventTracks}/> 
 
         
 
      </Modal> 
 
     ); 
 
    } 
 

 
    renderMenuEntries(entry) { 
 
     var switchState = entry.description; 
 
     return(
 
      <View style={styles.switchView}> 
 
       <Text style={[styleHelper.fonts.titleSize, styles.text]}>{entry.description}</Text> 
 
       <Switch onValueChange={(value) => this.switchChanged(switchState, value)} 
 
       value={this.state.switchState}/> 
 
      </View> 
 
     ); 
 
    } 
 

 

 
    switchChanged(field, value) { 
 
     var obj = {}; 
 
     obj[field] = value; 
 
     this.setState(obj); 
 
    } 
 
} 
 

 
var styles = StyleSheet.create({ 
 
    
 
}); 
 

 
module.exports = PopoverFilter;

で私のクラスを作成しました>filter.track -> All my JSON Objects

不足しているスタイルを無視してもしてくださいモーダルにはもっと多くのオブジェクトがありますが、この場合は重要ではありません。

最も重要なのは、すべてのスイッチをrenderMenuEntriesメソッドでレンダリングしようとしていて、すべてのエントリを与えることです。>スイッチだけが正しく設定されていません。私がスイッチの価値を変えようとする限り、即座にそのルートに戻ります。状態は設定されていません。

たぶん私の解決策は不可能であり、私はすべての状態が静的にする必要があります - しかし、この解決策は、私が

答えて

1

説明するシナリオが可能です。私はあなたのコードで発生した問題の数がありました:renderMenuEntries

  1. あなたは<Switch />コンポーネントに割り当てられた値は、代わりにその<Switch />コンポーネントvalue期待ブールの、データ項目の説明ました期待しています。さらに、この値は、存在しなかったthis.stateのプロパティも参照していました。

  2. switchChanged機能もちょうどあなたのコードサンプルは、私がPopoverFilterという名前のゼロから新しいクラスを作成して使用してデータ項目の説明

を使用してコンポーネントの状態を更新しました。このコンポーネント内でフィルタデータを要求するのではなく、filterDataという名前のコンポーネントのプロップを介してデータが入力されることを期待しています。これにより、異なるデータセットを受け入れるためのコンポーネントの再利用が促進されます。

コードは、実証された概念を説明するのに役立つと広くコメントされています。ここでPopoverFilterクラスがあります:

import React from 'react'; 
import { 
    ListView, 
    Modal, 
    Switch, 
    Text, 
    TouchableOpacity, 
    View 
} from 'react-native'; 

export default class PopoverFilter extends React.Component { 
    constructor (props) { 
    super(props); 

    // bind relevant handlers up front in the constructor 
    this.renderRow = this.renderRow.bind(this); 
    this.onPress = this.onPress.bind(this); 

    // process the incoming filter data to add a 'selected' property 
    // used to manage the selected state of its companion switch 
    this._filterData = this.processFilterData(this.props.filterData); 

    const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); 

    this.state = { 
     filterDataSource: ds.cloneWithRows(this._filterData) 
    } 
    } 

    processFilterData (filterData) { 
    // don't mutate the filterData prop coming in 
    // use map to create a new array and use Object.assign to make 
    // new object instances with a new property named 'selected' initialized 
    // with a value of false 
    return filterData.map((item) => Object.assign({}, item, { selected: false })); 
    } 

    switchChanged (rowId, isSelected) { 
    const index = +rowId; // rowId comes in as a string so coerce to a number 
    const data = this._filterData; 

    // don't mutate this._filterData 
    // instead create a new array and new object instance 
    this._filterData = [ 
     ...data.slice(0, index), // take everything before the target index 
     Object.assign({}, data[index], { selected: isSelected }), // create a new object instance with updated selected property 
     ...data.slice(index + 1) // take everything after the selected index 
    ]; 

    // update the listview datasource with the new data 
    this.setState({ 
     filterDataSource: this.state.filterDataSource.cloneWithRows(this._filterData) 
    }); 
    } 

    renderRow (item, sectionId, rowId) { 
    return(
     <View> 
     <Text>{item.description}</Text> 
     <Switch 
      onValueChange={(value) => this.switchChanged(rowId, value)} 
      value={item.selected} 
     /> 
     </View> 
    ); 
    } 

    // just a test function used to dump the current state of the _filterData 
    // to the console 
    onPress() { 
    console.log('data', this._filterData); 
    } 

    render() { 
    return (
     <Modal> 
     <ListView 
      renderRow={this.renderRow} 
      dataSource={this.state.filterDataSource} 
     /> 

     <TouchableOpacity onPress={this.onPress}> 
      <Text>Get Filter Data</Text> 
     </TouchableOpacity> 
     </Modal> 
    ); 
    } 
} 

(注)このPopoverFilterクラスはまた、あなたが、それは現在のフォームの表示できるように押されたときには、コンソールへのデータの現在の状態をダンプすることをボタンをレンダリングします。ここで

は、コンポーネントの使用方法の例です:

import React from 'react'; 
import { 
    AppRegistry, 
    View 
} from 'react-native'; 

import filterData from './filter'; 
import PopoverFilter from './PopoverFilter'; 

class MyApp extends React.Component { 
    render() { 
    return (
     <View> 
     <PopoverFilter filterData={filterData.filter.track} /> 
     </View> 
    ); 
    } 
} 

AppRegistry.registerComponent('MyApp',() => MyApp); 
+0

こんにちはメイソンを、最初にあなたの大切な、完全な応答をありがとうございました。私はあなたのソリューションをテストしようとし、それはかなりいいようです。あなたのソリューションを実装している限り私はフィードバックを提供します。ありがとうございました:) –

+0

こんにちはメーソン、私はあなたのソリューションをテストする時間があったし、私がやりたかったことに完全に適合します。あなたの詳細な提案とあなたが取った時間をありがとうございました。また、私は自分のコードでもっとうまくいくことができるかについてのさらなる情報にも感謝しています:) –

+1

これは素晴らしいジョナサンです。私はコードサンプルとヒントがあなたを助けてくれてうれしいです。この結果に満足している場合は、それを回答としてマークして、同じ問題を捜している他の人が解決策の恩恵を受けるようにしてください。 –

-1

を試してみて、全体のコードを変更せずに、動的フィルタを後から設定することができた場合に非常に良いでしょう
renderMenuEntries(entry) { 
    var switchState = entry.description; 
    return(
     <View style={styles.switchView}> 
      <Text style={[styleHelper.fonts.titleSize, styles.text]}>{entry.description}</Text> 
      <Switch onValueChange={(value) => this.switchChanged(switchState, value)} 
      value={this.state[switchState]}/> 
     </View> 
    ); 
} 


switchChanged(field, value) { 
    var obj = this.state; 
    obj[field] = value; 
    this.setState({obj}); 
} 
関連する問題