在React Native中从其他组件更新道具

时间:2019-05-31 13:59:17

标签: react-native components react-props

我有一个Main类,向用户显示一个数组,然后在详细页面中,用户可以使用react navigation参数编辑我要传递的每个元素。我想在detail类中编辑数组并使用异步存储将其保存。

//Main.jsimport React from 'react';
import {
    StyleSheet ,
     Text,
     View, 
     TextInput,
     ScrollView,
     TouchableOpacity,
     KeyboardAvoidingView,
     AsyncStorage
    } from 'react-native'
import Note from './Note'
import detail from './Details'
import { createStackNavigator, createAppContainer } from "react-navigation";


export default class Main extends React.Component {

  static navigationOptions = {
    title: 'To do list',
    headerStyle: {
      backgroundColor: '#f4511e',
    },
  };

  constructor(props){
    super(props);
    this.state = {
      noteArray: [],
      noteText: '',
      dueDate: ''
    };
  }

  async saveUserTasks(value) {
    try {
      await AsyncStorage.setItem('@MySuperStore:userTask',JSON.stringify(value));
    } catch (error) {
      console.log("Error saving data" + error);
    }
  }
   getUserTasks = async() =>{
    try {
      const value = await AsyncStorage.getItem('@MySuperStore:userTask');
      if (value !== null){
        this.setState({ noteArray: JSON.parse(value)});
      }
    } catch (error) {
      console.log("Error retrieving data" + error);
    }
  }

render() {
  this.getUserTasks()
    let notes = this.state.noteArray.map((val,key) => {
      return <Note key={key} keyval={key} val={val}
      deleteMethod={ () => this.deleteNote(key)}
      goToDetailPage= {() => this.goToNoteDetail(key)}
       />
    });
    const { navigation } = this.props;
    return(
      <KeyboardAvoidingView behavior='padding' style={styles.keyboard}>
        <View style={styles.container}>
            <ScrollView style={styles.scrollContainer}>
                {notes}
            </ScrollView>
            <View style={styles.footer}>
                <TextInput
                onChangeText={(noteText) => this.setState({noteText})}
                style={styles.textInput}
                placeholder='What is your next Task?'
                placeholderTextColor='white'
                underlineColorAndroid = 'transparent'
                >
                </TextInput>
            </View>
            <TouchableOpacity onPress={this.addNote.bind(this)} style={styles.addButton}>
                <Text style={styles.addButtonText}> + </Text>
            </TouchableOpacity>
        </View>
   </KeyboardAvoidingView>
      );
    }
    addNote(){
      if (this.state.noteText){
        var d = new Date();
        this.state.noteArray.push({ 
        'creationDate': d.getFullYear() + "/" + (d.getMonth()+1) + "/" + d.getDay(), 'taskName': this.state.noteText,'dueDate':'YYYY/MM/DD'
        });
        this.setState({noteArray:this.state.noteArray})
        this.setState({noteText: ''});
        this.saveUserTasks(this.state.noteArray) 
      }
    }
    deleteNote(key){
      this.state.noteArray.splice(key,1);
      this.setState({noteArray: this.state.noteArray})
      this.saveUserTasks(this.state.noteArray)       
    }
    goToNoteDetail=(key)=>{   
      this.props.navigation.navigate('DetailsScreen', {
        selectedTask: this.state.noteArray[key],
      });
    }     
}

在详细视图中,我有这种方法,类似于在主类中添加注释:

export default class Details extends React.Component {
  render() {
    const { navigation } = this.props;
    const selectedTask = navigation.getParam('selectedTask', 'task');
    return(
     <View key={this.props.keyval} style={styles.container}>
      <TouchableOpacity onPress={this.saveEdit.bind(this)} style={styles.saveButton}>
                <Text style={styles.saveButtonText}> save </Text>
      </TouchableOpacity>
    </View>
    );
  }
  saveEdit(){

    let selectedItem = { 'creationDate': selectedTask['creationDate'], 
    'taskName': selectedTask['taskName'],
    'dueDate': this.state.dueData}


this.props.navigation.state.params.saveEdit(selectedItem)
      }
    }

如何在任何组件中更改道具?

1 个答案:

答案 0 :(得分:1)

首先,您不应该在render方法中调用this.getUserTasks(),因为该函数具有this.setState不好,并且可能以无限循环结尾,我猜想或至少会导致性能下降。您可以改为在componentDidMount中调用它:

componentDidMount = () => {
    this.getUserTasks();
}

或者在构造函数中已经调用,但是我更喜欢第一个选项:

constructor(props){
  super(props);
  this.state = {
    noteArray: [],
    noteText: '',
    dueDate: ''
  };

  this.getUserTasks()
}

this.props.noteArray.push({..可能是未定义的,因为您没有将它传递到任何地方。(您的代码段中没有看到任何引用)。我想我会在Main.js组件,然后简单地将其传递到导航路径,然后通过访问导航状态props在Details组件中调用该函数:

更新

  goToNoteDetail=(key)=>{   
    this.props.navigation.navigate('DetailsScreen', {
      // selectedTask: this.state.noteArray[key],
      selectedItem: key,
      saveEdit: this.saveEdit
    });
  }     

  saveEdit(selectedItem){
    const selectedTask = this.state.noteArray[selectedItem]
    this.state.noteArray.push({ 
      'creationDate': selectedTask['creationDate'], 
      'taskName': selectedTask['taskName'],
      'dueDate': this.state.dueData
    });
    this.setState({noteArray:this.state.noteArray})
    this.setState({dueData: 'YYYY/MM/DD'});
    this.saveUserTasks(this.state.noteArray) 
  }

然后在“详细信息”组件中调用saveEdit:

saveSelectedItem = () => {
  const { navigation } = this.props.navigation;
  const {selectedItem, saveEdit} = navigation.state && navigation.state.params;
  saveEdit(selectedItem)
}