从数组 react-native 生成​​时,多个开关(切换开关)同时启用

IT技术 javascript arrays reactjs react-native
2021-05-25 01:42:39

现在我的构造函数中有一个这样的数组:

    words: ['test', 'test', 'test'],

在渲染中,我想生成一个带有文本的元素,并为每个元素切换(切换),如下所示:

const wordList = this.state.words.map((item, i) =>
    <View style={styles.wordsContainer}>
      <Text style={styles.pilgrimsWordText} key={i}>{item}</Text>
      <Switch
        style={styles.pilgrimsWordSwitch}
        onValueChange={(value) => {this.setState({ toggled: value })}}
        value={ this.state.toggled }
      />
    </View>
 )

之后我只显示返回中的元素。

元素被生成,一切看起来都很好,但是当用户按下其中一个(切换)时,所有元素都会像图片一样被启用:

元素的图片(带有文本和开关)

你会怎么做才能启用用户希望启用的一个开关(切换)?

__________ 编辑:___________ 这是我的构造函数:

 constructor(props) {
   super(props);
   this.state = {
     words: [{ id: 1, text: 'test'}, { id: 2, text: 'test'}, {id: 3, text: 'test'}],
     textInputValue: '',
   }
  }

现在地图看起来像这样:

const wordList = this.state.words.map((item, i) =>
    <View style={styles.wordsContainer}>
      <Text style={styles.pilgrimsWordText} key={item.id}>{item.text}</Text>
      <Switch
        style={styles.pilgrimsWordSwitch}
        onValueChange={(value) => {this.setState({ toggled: { [item.id]: value }})}}
        value={ this.state.toggled[item.id] }
      />
    </View>
 )

这是错误:

错误的图像

4个回答

我认为您必须跟踪元素索引并words在我的示例中重构您的数据

class Example extends React.Component {
    constructor(props){
    super(props);
    this.state = {
      words: [
        {text: 'test', toggled: false},
        {text: 'test', toggled: false},
        {text: 'test', toggled: false}
      ]
    }
  }

  toggle(index, e){
    const words = [...this.state.words];
    words[index].toggled = !words[index].toggled;

    this.setState({ words });
  }

  render() {
    return (
        <div>
        {this.state.words.map((word, i) =>
            <span key={i}>
              {word.text}
              <input type="checkbox" onChange={this.toggle.bind(this, i)} />
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                   //bind a function with element index you just clicked
            </span>
        )}
        <br/><br/>
        {JSON.stringify(this.state.words)}
      </div>
    )
  }
}

Worked example

发生这种情况是因为每个映射组件都使用相同的状态变量来确定它是否处于“切换”状态。您将需要使用 3 个不同的状态变量,但如果列表的长度未知,这将变得更加困难。

您需要在数据/数组中使用唯一标识符来实现所需的行为。

如果您对数据进行如下更改,您可以为每个映射组件设置唯一的状态值。

words: [{ id: 1, text: 'test'}, { id: 2, text: 'test'}, {id: 3, text: 'test'}],

const wordList = this.state.words.map((item, i) =>
    <View style={styles.wordsContainer}>
      <Text style={styles.pilgrimsWordText} key={item.id}>{item.text}</Text>
      <Switch
        style={styles.pilgrimsWordSwitch}
        onValueChange={(value) => {this.setState({ toggled: { [item.id]: value })}}
        value={ this.state.toggled[item.id] }
      />
    </View>
 )

在构造函数中将初始切换状态值设置为这样的空对象 {}

Array.map 为数组中的每个元素调用一次提供的回调函数,该回调函数使用三个参数调用:元素{}的值、元素索引被遍历Array 对象

import React, { Component} from 'react';
import {
  Dimensions,
  StyleSheet,
  Switch,
  Text,
  View,
} from 'react-native';

const { height, width } = Dimensions.get('window');

export default class WordList extends Component {

  constructor(props: Object) {
    super(props);
    this.state = {
      words: [
        { id: 1, text: 'Notification', toggle:false}, 
        { id: 2, text: 'Wifi', toggle:false}, 
        { id: 3, text: 'Bluetooth', toggle:false}
      ]
    }
  };

 renderWordList(){
    const wordList = this.state.words.map((word, i, wordArray) =>
      <View key={word.id} style={styles.wordsContainer}>
        <Text>{word.text}</Text>
        <Switch
          style={styles.pilgrimsWordSwitch}
          onValueChange={(toggleValue) => {
            wordArray[i].toggle = toggleValue;
            this.setState({words: wordArray});
          }}
          value={ word.toggle }
        />
      </View>
    )
    return wordList;
  }

  render() {
    return (
      <View style={{flex: 1, justifyContent:'center', backgroundColor: 'gray'}}>
        {this.renderWordList()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  wordsContainer: {
    alignItems:'center', 
    backgroundColor:'green',  
    flexDirection:'row',
    height:100, 
    ustifyContent:'center', 
    padding:20,
  },
  pilgrimsWordSwitch: {
    flex:1, 
    justifyContent:'flex-end'
  }
});

上述代码的渲染视图