更新来自其他组件的道具反应原生

Posted

技术标签:

【中文标题】更新来自其他组件的道具反应原生【英文标题】:Update props from other component in react native 【发布时间】:2019-10-17 04:31:25 【问题描述】:

我有一个 Main 类,我向用户显示一个数组,然后详细页面用户可以编辑我使用 react 导航参数传递的每个元素。我想在详细信息类中编辑我的数组并使用异步存储进行保存。

//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】:

首先,您不应该在 render 方法中调用 this.getUserTasks(),因为该函数的 this.setState 很糟糕,我猜它可能会以无限循环结束,或者至少会影响性能。您可以改为在 componentDidMount 中调用它:

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

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

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

  this.getUserTasks()

this.props.noteArray.push(.. 可能是未定义的,因为你没有将它传递到任何地方。(在你的 sn-p 中没有看到任何引用)。我想我会实现 saveEdit 函数在 Main.js 组件中,只需将其传递给导航路由,并通过访问导航状态道具调用 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) 
  

然后在Details组件中调用saveEdit:

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

【讨论】:

那我应该如何实现 saveEdit 方法,以便我可以传递 ' 'creationDate': selectedTask['creationDate'], 'taskName': selectedTask['taskName'],'dueDate':this.state .dueData' 这个来自详细组件 @Niloufar 检查我的更新。当您导航到详细信息屏幕时,您将键设置为 selectedItem(如果您愿意,也可以将其设置为“键”)。然后,当您从 Details 组件调用 saveEdit 时,只需将 selectedItem 作为参数传递来识别当前/选定的任务以更新任务。希望这会有所帮助 谢谢,但是这行 const selectedItem, saveEdit = navigation.state && navigation.state.params; 我仍然有错误“未定义不是一个对象(评估'navigation.state') 亲爱的 BigPun 请检查我的更新,这样你就会知道我的代码是否有任何错误,我是反应原生的新手并且很困惑 我试图再次检查您的解决方案,但现在我得到'未定义不是对象(评估'navigation.state')

以上是关于更新来自其他组件的道具反应原生的主要内容,如果未能解决你的问题,请参考以下文章

反应原生如何检查组件当前是不是显示在屏幕中

更新道具时反应本机组件不透明度不更新

当用户输入通过来自另一个组件的道具的文本时,在反应 js 中不起作用

javascript 用于重构的增强器,用于记录反应组件更新中更改的道具

相机不显示,状态转换问题,反应原生

反应原生 Typescript Touchableopacity 道具错误