在React Native中保存数据并发送到另一个类

时间:2018-05-14 17:11:30

标签: react-native

我正在处理的应用程序有点问题。我必须做一个像笔记应用程序的东西。我有一个按钮,可以将我导航到另一个屏幕,我可以在其中编写注释,我有一个保存按钮,可以将我发送回预览屏幕,并scrollview更新

以下是我迄今为止所做的尝试:

App.js:

import React, { Component } from 'react';
import Main from './app/components/Main.js';
import NoteBody from './app/components/NoteBody.js';
import {StackNavigator} from 'react-navigation'


const App = StackNavigator({Home: {screen: Main}, WriteNote: {screen: NoteBody}});

export default App;

Main.js:

import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
ScrollView,
TouchableOpacity,
AsyncStorage,
} from 'react-native';

import Note from './Note';
import NoteBody from './NoteBody.js';

export default class Main extends Component {

static navigationOptions = {
    title: 'Notes',
};

constructor(props){
    super(props);
    this.state = {
        noteArray: [],
        noteText: '',
    };
}
    componentDidMount(){
    this.getSavedNotes(this.state.noteArray);
}
render() {
    let notes = this.state.noteArray.map((val, key)=>{
        return <Note key={key} keyval={key} val={val}
                deleteMethod={()=>this.deleteNote(key)}/>
    });

    const { navigate } = this.props.navigation;

    return (
        <View style={styles.container}>
            <ScrollView style={styles.scrollViewContainer}>
                <ScrollView style={styles.scrollContainer}>
                {notes}
                </ScrollView>
                <TouchableOpacity onPress={() =>
                    navigate('WriteNote' ,{onNavigateBack:
 this.handleOnNavigateBack.bind(this)})} 
                    style={styles.addButton}>
                        <Text style={styles.addButtonText}>+</Text>
                        <Text style={styles.addButtonAditionalText}>Add note</Text>
                </TouchableOpacity>
            </ScrollView>
        </View>

    );
}


deleteNote(key){
    this.state.noteArray.splice(key, 1);
    this.setState({noteArray: this.state.noteArray});
    AsyncStorage.setItem('arr', JSON.stringify(this.state.noteArray));
//     alert(this.state.noteArray);
 }

getSavedNotes = async (noteArray) =>{
  try{
    let data = await AsyncStorage.getItem('arr');
    if(JSON.parse(data))
    {
      this.setState({noteArray: JSON.parse(data)});
    }
  }catch(error){
    alert(error);
  }
}
}


const styles = StyleSheet.create({
container: {
    flex: 1,
},
scrollContainer: {
    flex: 1,
},

addButton: {
    position: 'relative',
    zIndex: 11,
    left: 0,
    top: 0,
    alignItems: 'flex-start',
    justifyContent: 'flex-end',
    width: 100,
    height: 60,
    elevation: 8
},
addButtonText: {
    color: '#000',
    fontSize: 60,
},
addButtonAditionalText: {
    color: '#000',
    fontSize: 12,
    marginLeft: 40,
    position: 'absolute',
    bottom: 20,
},
scrollViewContainer: {
    flex: 1,
    marginBottom: 70,
}
});

Note.js:我们有scrollview以及导航到NoteBody屏幕的按钮。

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


export default class Note extends Component {
render() {
    return (
        <View key={this.props.keyval} style={styles.note}>
            <Text style={styles.noteText}>{this.props.val.date}</Text>
            <Text style={styles.noteText}>{this.props.val.note}</Text>

            <TouchableOpacity onPress={this.props.deleteMethod} style={styles.noteDelete}>
                <Text style={styles.noteDeleteText}>Del</Text>
            </TouchableOpacity>
        </View>
    );
}
}


const styles = StyleSheet.create({
note: {
    position: 'relative',
    padding: 20,
    paddingRight: 100,
    borderBottomWidth:2,
    borderBottomColor: '#ededed'
},
noteText: {
    paddingLeft: 20,
    borderLeftWidth: 10,
    borderLeftColor: '#0000FF'
},
noteDelete: {
    position: 'absolute',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#2980b9',
    padding: 10,
    top: 10,
    bottom: 10,
    right: 10
},
noteDeleteText: {
    color: 'white'
}
});

最后是NoteBody:您可以在这里编写注释的正文,并且您还有一个保存按钮,该按钮还应该将数据保存在AsyncStorage中,这样即使应用程序关闭后我也可以显示它。 / p>

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

import Note from './Note.js';

export default class NoteBody extends Component {
    static navigationOptions = {
    title: 'Note',
};

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

render() {
    let notes = this.state.noteArray.map((val, key)=>{
        return <Note key={key} keyval={key} val={val}
                deleteMethod={()=>this.deleteNote(key)}/>
    });

    return (
        <View style={styles.container}>
            <View style={styles.noteBody}>
                <TextInput 
                    multiline = {true}
                    numberOfLines = {1000000}
                    style={styles.textInput}
                    placeholder='Write your note here'
                    onChangeText={(noteText)=> this.setState({noteText})}
                    value={this.state.noteText}
                    placeholderTextColor='grey'
                    underlineColorAndroid='transparent'>
                </TextInput>
            </View>
            <TouchableOpacity onPress={ this.addNote.bind(this) } style={styles.addButton}>
                        <Text style={styles.addButtonText}>SAVE</Text>
            </TouchableOpacity>
        </View>
    );
}

addNote(){
    const { navigate } = this.props.navigation;
    if(this.state.noteText){
        var d = new Date();
        this.state.noteArray.push({
            'date':d.getFullYear()+
            "/"+(d.getMonth()+1) +
            "/"+ d.getDate(),
            'note': this.state.noteText
        });

        this.setState({ noteArray: this.state.noteArray });
        this.setState({noteText:''});
        AsyncStorage.setItem('arr', JSON.stringify(this.state.noteArray));
        this.props.navigation.state.params.onNavigateBack();
        navigate('Home');
        // alert(this.state.noteArray);
    }
}
getSavedNotes = async (noteArray) =>{
  try{
    let data = await AsyncStorage.getItem('arr');
    if(JSON.parse(data))
    {
      this.setState({noteArray: JSON.parse(data)});
    }
  }catch(error){
    alert(error);
  }
}
}


const styles = StyleSheet.create({
container: {
    flex: 1,
},
noteBody:{
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    zIndex: 10,
    alignItems: 'center',
    borderBottomWidth:1,
    borderTopColor: '#000',
    marginBottom: 100,
},
textInput: {
    alignSelf: 'stretch',
    textAlignVertical: 'top',
    backgroundColor: '#fff',
    color: '#000',
    padding: 20,
    borderTopWidth:2,
    borderTopColor: '#ededed',
},
addButton: {
    position: 'absolute',
    zIndex: 11,
    left: 0,
    bottom: 0,
    alignItems: 'center',
    justifyContent: 'center',
    width: 300,
    backgroundColor: '#00FF00',
    height: 60,
    elevation: 8
},
addButtonText: {
    color: '#fff',
    fontSize: 24,
},

});

保存按钮仅保存我写的最后一个音符,它甚至不会立即显示在scrollview上。我必须重新打开应用程序才能显示它。

3 个答案:

答案 0 :(得分:1)

这里有一些错误:

首先,您只需在Main组件的构造函数中获取已保存的注释,该注释仅在实例化时调用。放置此代码的建议位置在componentDidMount()中。另外我不明白你为什么要将noteArray状态传递给你的getSavedNotes()方法。

接下来,这是一个重要的问题:从数组添加和删除注释的方法是变异的(拼接和推送)。由于React使用浅比较来确定何时重新渲染,因此在使用setState()时需要创建一个新对象。因此,对于添加,您可以使用concat(),对于删除,Lodash的omit()函数非常有用。或者,您可以使用扩展运算符。

免责声明:我还没有详细阅读您的所有代码,因此可能还有一些其他问题。

编辑:使用FlatList

// render() method of Main.js
render() {

    const { navigate } = this.props.navigation;

    return (
    <View style={styles.container}>
        <ScrollView style={styles.scrollViewContainer}>
            <ScrollView style={styles.scrollContainer}>
                <FlatList
                    data={this.state.noteArray}
                    renderItem={({item, index}) => this.renderItem(item, index)}
                    keyExtractor={(item, index) => `${index}`}
                />
            </ScrollView>
            <TouchableOpacity onPress={() =>
                navigate('WriteNote')} 
                style={styles.addButton}>
                    <Text style={styles.addButtonText}>+</Text>
                    <Text style={styles.addButtonAditionalText}>Add note</Text>
            </TouchableOpacity>
        </ScrollView>
    </View>
    );
}

renderItem = (item, index) => {
    return (
        <Note 
            keyval={index}
            val={item}
            deleteMethod={()=>this.deleteNote(index)}
        />
    );
} 

答案 1 :(得分:0)

看起来您可以在Main.js中添加listener以获得&#39; onFocus&#39;事件。我会使用回调来查询AsyncStorage并使用结果设置状态。

答案 2 :(得分:0)

屏幕A. 在屏幕A中执行从屏幕B导航回来时想要发生的事情的方法:

handleOnNavigateBack = (foo) => {

this.setState({     FOO   })     }

这是屏幕A中的React Navigation方法导航到屏幕B:

this.props.navigation.navigate('ScreenB', {
 onNavigateBack: this.handleOnNavigateBack})

...或者如果你的handleOnNavigateBack函数不是一个箭头函数(绑定它),你需要绑定它:(ht @stanica)

this.props.navigation.navigate('ScreenB', {

onNavigateBack:this.handleOnNavigateBack.bind(this)     })

屏幕B. 导航到屏幕B并准备导航回屏幕A ...

调用该函数(从屏幕A传递到屏幕B)来执行屏幕A中的操作:

this.props.navigation.state.params.onNavigateBack(this.state.foo)

然后调用React Navigation方法返回(到屏幕A):

this.props.navigation.goBack()

我还更新了我的问题代码,因此它是假定要执行的版本。