[英]react-native: send complete STATE from one component to another?
I have a Reminder component
comprising of a form where I am storing text and date onClick of a button using AsyncStorage
. 我有一个
Reminder component
其中包含一个表单,其中使用AsyncStorage
存储按钮的文本和日期onClick。
Now, I want to display this stored data in Agenda Component
. 现在,我想在
Agenda Component
显示此存储的数据。
I am using Agenda component
from react-native-calendars
library react-native-calendars 我正在使用来自
react-native-calendars
库的Agenda component
react-native-calendars
this is my reminder component
这是我的
reminder component
class Reminder extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
chosenDate: new Date(),
};
this.setDate = this.setDate.bind(this);
this.handleChangeInput = this.handleChangeInput.bind(this);
this.saveData = this.saveData.bind(this);
}
setDate(newDate) {
this.setState({
chosenDate: newDate
});
}
handleChangeInput = (text) => {
this.setState({input:text});
}
//save the input
saveData() {
AsyncStorage.setItem("key", JSON.stringify(this.state));
}
render() {
return (
<View>
<Form style={styles.formContainer}>
<View style={styles.formView}>
< TextInput
placeholder = "Set your reminder"
onChangeText={this.handleChangeInput}
value={this.state.input}
/>
<DatePicker
defaultDate={new Date()}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2019, 12, 31)}
locale={"en"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={false}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate}
/>
<Text style={styles.datePicker}>
{this.state.chosenDate.toString().substring(0,10)}
</Text>
</View>
<View style={styles.footer}>
<Button block success style={styles.saveBtn}
onPress={ () =>
{
this.saveData()
console.log('save data',this.state);
}
}
>
<Icon type='MaterialIcons' name='done' />
</Button>
</View>
</Form>
</View>
);
}
}
export default Reminder;
and this it's screen Reminder screen
这是屏幕
Reminder screen
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import PropTypes from 'prop-types';
import Reminder from '../components/Reminder';
const ReminderScreen = ({navigation}) => (
<View >
<Reminder navigation={navigation} >
<StatusBar backgroundColor = "#28F1A6" />
</Reminder >
</View>
);
Reminder.propTypes = {
navigation: PropTypes.object.isRequired
}
export default ReminderScreen;
and this is the component I want to display that data Agenda Component
这是我要显示该数据的
Agenda Component
class WeeklyAgenda extends Component {
constructor(props) {
super(props);
this.state = {
items: {},
selectedDate: ''
};
}
render() {
return (
<View style={{height:600}}>
<Agenda
items={this.state.items}
loadItemsForMonth={this.loadItems.bind(this)}
selected={this.props.day}
renderItem={this.renderItem.bind(this)}
renderEmptyData={this.renderEmptyDate.bind(this)}
rowHasChanged={this.rowHasChanged.bind(this)}
onRefresh = {() => { this.setState({refeshing : true})}}
refreshing = {this.state.refreshing}
refreshControl = {null}
pastScrollRange={1}
futureScrollRange = {3}
theme = {
{
agendaTodayColor: '#28F1A6',
agendaKnobColor: '#28F1A6',
dotColor: '#28F1A6',
selectedDayBackgroundColor: '#28F1A6',
todayTextColor: '#28F1A6',
}
}
/>
<View >
<Fab
active={!this.state.active}
direction="up"
style={{ backgroundColor: '#28F1A6'}}
position = 'bottomRight'
onPress={() => this.props.navigation.navigate('Reminder')}>
<Icon type='MaterialCommunityIcons' name="reminder" />
</Fab>
</View>
</View>
);
}
//On application loads, this will get the already saved data and set the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("key").then((newItems) => {
this.setState(JSON.parse(newItems));
});
}
loadItems = (day) => {
console.log('day',day);
console.log('items', this.state.items);
const {selectedDate} = this.state;
setTimeout(() => {
console.log('selected date', selectedDate);
this.setState({selectedDate: day});
console.log('selected date later', day);
const newItems = {};
Object.keys(this.state.items).forEach(key => {newItems[key] = this.state.items[key];});
console.log('new items later', newItems);
this.setState({
items: newItems
});
console.log('new items later', this.state.newItems);
console.log('items later', this.state.items);
this.state.items;
},1000);
};
renderItem(item) {
return (
<View style={[styles.item, {height: item.height}]}>
<TouchableOpacity onPress={() => {this.props.navigation.navigate('Reminder')}}>
<Text>{item.name}</Text>
</TouchableOpacity>
</View>
);
}
renderEmptyDate() {
return (
<View style={styles.emptyDate}>
<TouchableOpacity onPress={() => {this.props.navigation.navigate('Reminder')}}>
<Text style={styles.emptyTextColor}> No Event or Reminder on this date </Text>
</TouchableOpacity>
</View>
);
}
rowHasChanged(r1, r2) {
return r1.name !== r2.name;
}
timeToString(time) {
const date = new Date(time);
return date.toISOString().split('T')[0];
}
}
export default WeeklyAgenda;
and this is it's screen Agenda Screen
这是屏幕
Agenda Screen
import React, { Component } from 'react';
import { View, Text, StatusBar } from 'react-native';
import PropTypes from 'prop-types';
import WeeklyAgenda from '../components/Agenda';
class AgendaScreen extends Component {
state = { }
render() {
const {navigation} = this.props;
const { params } = this.props.navigation.state;
return (
<View style={{height: 100}}>
<WeeklyAgenda day={params["day"]} navigation={navigation}>
<StatusBar backgroundColor="#28F1A6" />
</WeeklyAgenda >
</View>
);
}
}
WeeklyAgenda.propTypes = {
navigation: PropTypes.object.isRequired
}
export default AgendaScreen;
I am fairly new to react-native and still trying to figure out how to share data between components and screens. 我对本机响应还很陌生,但仍在尝试弄清楚如何在组件和屏幕之间共享数据。
So basically in react-native data flow between components involves props. 因此,基本上,组件之间的本机数据流都涉及道具。 In case you need to pass the entire state of one component to another, you can pass props to the second component by stringifying the state and recieve the prop by parsing it to json object again.
如果需要将一个组件的整个状态传递给另一个组件,则可以通过对状态进行字符串化来将props传递给第二个组件,并通过再次将其解析为json对象来接收prop。
If you are using any navigation to navigate between components and screens, you can also use passProps to send state to next screen. 如果使用任何导航在组件和屏幕之间导航,则还可以使用passProps将状态发送到下一个屏幕。 Hope this helps.
希望这可以帮助。
To do this you want to take your items and map them in your Agenda component. 为此,您需要拿走物品并将其映射到“议程”组件中。 I don't know what props the item object contains so I just made up item.name and item.whatever.
我不知道item对象包含什么道具,所以我只是组成了item.name和item.whatever。 I also didn't know how you wanted to display this data.
我也不知道您想如何显示这些数据。 You can display it however you like in the return statement of the map function.
您可以根据需要在map函数的return语句中显示它。
If you want a table just have to render a table in the return statement and dynamically add your item props accordingly. 如果您想要一个表,只需在return语句中呈现一个表,并相应地动态添加您的道具。 Does this make sense?
这有意义吗?
Also, the outermost element of your return in your map function must have a key prop that accepts unique keys only. 同样,您在map函数中返回的最外层元素必须具有仅接受唯一键的键属性。
state = {
items: [],
selectedDate: ''
}
render() {
const { items } = this.state; // destructure state, so create a variable called items that is equal to this.state.items essentially takes the items in the state variable items and copies them to a new const variable called items
return (
<View style={{height:600}}>
<Agenda
items={items} //send those items to Agenda Component via prop
loadItemsForMonth={this.loadItems.bind(this)}
selected={this.props.day}
renderItem={this.renderItem.bind(this)}
renderEmptyData={this.renderEmptyDate.bind(this)}
rowHasChanged={this.rowHasChanged.bind(this)}
onRefresh = {() => { this.setState({refeshing : true})}}
refreshing = {this.state.refreshing}
refreshControl = {null}
pastScrollRange={1}
futureScrollRange = {3}
theme = {
{
agendaTodayColor: '#28F1A6',
agendaKnobColor: '#28F1A6',
dotColor: '#28F1A6',
selectedDayBackgroundColor: '#28F1A6',
todayTextColor: '#28F1A6',
}
}
/>
);
}
//On application loads, this will get the already saved data and set the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("key").then((newItems) => {
//assuming JSON.parse returns an array of JSON objects, if not change
//items to items: {} the way you had it originally in state
this.setState({ items: JSON.parse(newItems) }) //add the items or data to state variable called items
});
}
}
//let's pretend that this is your Agenda Component //让我们假装这是您的议程组件
class Agenda extends Component {
state = {
items: this.props.items, //get the items that were passed above using items={item} and assign them to a state variable items here in the Agenda component
}
render() {
const { items } = this.state; //destructure state
return(
<div>
//put this where you want to render the data in the AgendaComponent you said you were using a Text Component so it would like this
items.map(item => {
return (
//assuming that item object comes with an id if not you must add a unique key so you can call a func that updates a count variable and returns it
<Text key={item.id}>{item.name} {item.date}</Text>
)
})
)
</div>
}
}
remember. 记得。 the map function is almost like a for loop.
map函数几乎就像一个for循环。 It will iterate through every element in the array and do what is in the return statement for each element of the array.
它将遍历数组中的每个元素,并对数组中的每个元素执行return语句中的操作。
Hope this helps. 希望这可以帮助。
The previous solution I wrote out had a bug. 我以前写的解决方案有一个错误。 The Agenda component was setting the state before it actually received props and did not update the state when props updated.
议程组件在实际接收道具之前设置状态,并且在道具更新时未更新状态。
For some reason, componentWillReceiveProps never got any props. 由于某些原因,componentWillReceiveProps从未获得任何道具。 However, componentDidUpdate received props after one update.
但是,componentDidUpdate在一次更新后收到了道具。 The issue is that you cannot
setState
in componentDidUpdate()
or you will get an infinite loop. 问题是您不能在
componentDidUpdate()
setState
,否则将发生无限循环。 So here is a work around. 所以这里是一个解决方法。 If anyone has a better solution to this please edit my answer or post a new answer with that.
如果有人对此有更好的解决方案,请编辑我的答案或发布新答案。
The following is only for your Agenda Component. 以下内容仅适用于您的议程组件。 Nothing else needs updating
没什么需要更新的了
First, update your state declaration from this: 首先,从此更新您的状态声明:
state = { items: this.props.items, //get the items that were passed above using items={item} and assign them to a state variable items here in the Agenda component } state = {items:this.props.items,//使用items = {item}获取上面传递的项目,并将它们分配给Agenda组件中的状态变量items}
to this: 对此:
state = {
items: null, //changed this to null bc the array gave a nested array later on making it more difficult to traverse through
haveItems: false //this will be used later to check if there are items available in props to update state
};
In your render()
function change this 在您的
render()
函数中更改此
render() { const { items } = this.state; render(){const {items} = this.state; //destructure state return( //put this where you want to render the data in the AgendaComponent you said you were using a Text Component so it would like this items.map(item => { return ( //assuming that item object comes with an id if not you must add a unique key so you can call a func that updates a count variable and returns it {item.name} {item.date} ) }) ) } }
// destruct state return(//将其放在您要使用文本组件在AgendaComponent中呈现数据的位置,因此需要此items.map(item => {return(//假设该item对象来了如果没有ID,则必须添加一个唯一键,以便您可以调用一个函数来更新计数变量并返回它。{item.name} {item.date}}}))}}
to this: 对此:
const { items, haveItems } = this.state; //destructure state
if (this.props.items.length === 0) {
this.setState({ haveItems: false }); //if there aren't any items in props then you have no items so set haveItems to false
} else {
//if you already have items then you already handled those items so do nothing
if (haveItems) {
} else {
//handle the items
this.setState({
haveItems: true, //set this to true bc now you have items
items: this.props.items //set items in state to the items in props, you will get one array with all of your objects
});
}
}
return (
<div>
<div>
{haveItems
{* if you have items then map them the question mark means true, if not display nothing, the colon : means false
? items.map(item => {
return (
<ul key={item.id}>
<li>{item.name}</li>
<li>{item.date}</li>
</ul>
);
})
: null}
</div>
</div>
);
}
}
Sorry for a long answer but I hope this is what you needed. 对不起,很长的答案,但我希望这是您所需要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.