我想在按下其中一个特殊 child 时更改多个 child 的背景

I want to change background of a more than one child on press of one of the special child

你好,我刚开始学习react native,一直卡在这。我不确定这是正确的做法还是需要改变。请帮忙。

我有一个 parent 组件和一个 child 组件。 Parent 包含平面列表和渲染 child。如果一个child很特别那么想改变多个child的背景,如果不是那么只有他的背景会改变。

class Parent extends Component {

 constructor(props){
  a = ['a','h','n','1','2','3'];
  this.state={
   list=a,
  };
}

render(){
 return (
  <View>
   <FlatList
      data={this.state.list}
      renderItem={(item) => (
          <Child name={item['item']} />)} />
  </View>
 )
}
}

class Child extends Component {
 constructor(props){
  this.state={
   itemState:"off"
 }

 pressed(name){
  //if name is alpha it's special change background of multiple.
  //else change background of this only.
 }

 getImage(){
  if(this.state.itemState === "on){
   return require('onImgPath')
  else
   return require('offImgPath')
 }
 render(){
 var imgp=this.getImage();
  return (
   <TouchableOpacity onPress={this.pressed.bind(this,this.props.name)>
    <ImageBackground source={imgp}> 
     <Text>{this.props.name}</Text>
    </ImageBackground>
   </TouchableOpacity>
  )
 }
}

按下平面列表项目即 child 我想更改图像。这将基于 child 的名称,如果其 'a' 那么所有非特殊 child 将背景更改为 'on'。如果 'h' 那么只有前半部分会变成 'on' 而其他部分会变成 'off' 如果它是 'n' 那么所有非特殊的都会变成关闭图像。

请告知如何使它工作以及哪种方式应该适合处理这种情况。

你应该精确:

如果名字是alpha它是multiple的特殊变化背景

更正

这是对您的代码的可能更正:

import React, { Component } from 'react';
import  {  StyleSheet, View, FlatList, Text, ImageBackground,TouchableOpacity } from 'react-native';

export default class Parent extends Component {

 constructor(props){
     super(props);

  let a = ['a','h','n','1','2','3'];

   this.state={
     list:a,
   };
}

_renderItem = ({ item, index }) => (<Child name={item} /> );

render(){
 return (
   <View style={styles.container}>
    <FlatList
        data={this.state.list}
        renderItem= {this._renderItem}/>
   </View>
    )
  }
}

class Child extends Component {
 constructor(props){
  super(props);

  this.state={
  itemState:true,
  }
}

pressed = () => {
  if(this.props.name === 'alpha'){
   // Do stuffs
 }

  this.setState({itemState:!this.state.itemState});
  console.log(this.props.name);  
}

render(){ 
   return (
     <TouchableOpacity style={styles.container} onPress={()=>this.pressed()} style={{ width: '100%', height: 80 }}>
        <ImageBackground source={this.state.itemState === true ?  require('assets/on.png') :  require('assets/off.png')} style={styles.image}> 
           <Text style={styles.text}>{this.props.name}</Text>
        </ImageBackground>
      </TouchableOpacity>
     )
    }
   }

const styles = StyleSheet.create({
 container: {
  flex: 1,
   },
  text : {
   fontSize:16, 
   marginLeft:20, 
   color:'white'
  },
  image : { width: '100%', height: '100%' }
})

开始屏幕

单击了 'n' 和“2”

结论

  • 你必须在构造函数中调用'super'
  • 注意关闭所有打开的括号:{}
  • 看看你的代码有什么不同,学习和享受吧!

更准确的答案

如果我查看此线程标题中的问题,一种解决方案是在 parent 组件中控制 children 的状态。在这种情况下,您必须考虑 children 的行为。

这是一个解决方案:

import React, { Component } from 'react';
import  {  StyleSheet, View, FlatList, Text, ImageBackground,TouchableOpacity } from 'react-native';

let a = [
  {name :'a',itemState: true,linked:['n','1']}, 
  {name :'h',itemState: true}, 
  {name :'n',itemState: true}, 
  {name :'1',itemState: true}, 
  {name :'2',itemState: true,linked:['h']}, 
  {name :'3',itemState: true}
];

export default class Parent extends Component {

 constructor(props){
   //Never forget to call super()
   super(props);
   this.state={
   list:a,
   listLinked : []
 };
}

//Don't forget to pass the callBack function
//This callBack process the state of items in list
_renderItem = ({ item, index }) => (<Child item={item} callBack={this._callBack}/> );

_callBack = (entrie) => {
//Look if item has linked elements and do the job
if (undefined != entrie.item.linked){
    for(var i=0; i< entrie.item.linked.length; i++){
       var indexLinkedItem = a.findIndex(element => element.name===entrie.item.linked[i]);
       //Here you must think to the behaviour of your function
       //By default, I toggle the actuel state of the linked item
       //If you want to force them to be true or false
       //You have to write : 
       // a[indexLinkedItem].itemState = true
       //or
       // a[indexLinkedItem].itemState = false

         a[indexLinkedItem].itemState = !a[indexLinkedItem].itemState;
        }
    }
//In all case, the state of the pressed item change
   var indexItem = a.findIndex(element => element.name===entrie.item.name);
   a[indexItem].itemState = !a[indexItem].itemState;

//Assign the new list a to the state
  this.setState({list : a});
}

render(){
console.log('main');
 return (
  <View style={styles.container}>
    <FlatList
        data={this.state.list}
        renderItem= {this._renderItem}
        //Use extraData to be sure flatlist rerender after _callBack
        extraData={this.state}/>
  </View>
    )
  }
}

class Child extends Component {
//This is a stateless component

pressed = () => {
 this.props.callBack(this.props);
}

render(){
return (
   <TouchableOpacity style={styles.container} onPress={()=>this.pressed()} style={{ width: '100%', height: 80 }}>
      <ImageBackground source={this.props.item.itemState === true ?  require('assets/on.png') :  require('assets/off.png')} style={styles.image}> 
         <Text style={styles.text}>{this.props.item.name}</Text>
      </ImageBackground>
   </TouchableOpacity>
  )
 }
}

//This is the style you can change
//ImageBackground must have size
const styles = StyleSheet.create({
 container: {
 flex: 1,
 },
text : {
  fontSize:16, 
  marginLeft:20, 
  color:'white'
  },
  image : { width: '100%', height: '100%' }
})

在开始屏幕上,当我单击第一个项目 'a' 时,链接项目 'n' 和“1”的状态也会发生变化:

结论

你想我现在点'n'会怎么样? 它只改变'n'的状态还是'a'、'n'和'1'的状态? 如果您有另一个项目与 'a'、'n' 或 '1' 链接会怎样?

在此处观看实际代码:

https://www.youtube.com/watch?v=tmsfhZ53zNE&feature=youtu.be