我有一个Reminder component
,其中包含一个表单,其中我使用AsyncStorage
来单击按钮时存储文本和日期。
现在,我想在Agenda Component
中显示此存储的数据。
我正在使用Agenda component
库react-native-calendars中的react-native-calendars
这是我的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;
这是屏幕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;
这是我要显示数据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;
这是屏幕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;
我对本机反应还很陌生,但仍在尝试弄清楚如何在组件和屏幕之间共享数据。
答案 0 :(得分:0)
因此,基本上,组件之间的本机数据流涉及道具。如果需要将一个组件的整个状态传递给另一组件,则可以通过对状态进行字符串化来将props传递给第二个组件,并通过将其再次解析为json对象来接收prop。
如果使用任何导航在组件和屏幕之间导航,则还可以使用passProps将状态发送到下一个屏幕。希望这会有所帮助。
答案 1 :(得分:0)
要执行此操作,您需要拿走物品并将其映射到Agenda组件中。我不知道item对象包含什么道具,所以我只是组成了item.name和item.whatever。我也不知道您想如何显示这些数据。您可以根据需要在map函数的return语句中显示它。
如果您想要一个表,只需要在return语句中呈现一个表并相应地动态添加您的道具即可。这有意义吗?
此外,您在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
});
}
}
///让我们假装这是您的议程组件
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>
}
}
记住。 map函数几乎就像一个for循环。它将遍历数组中的每个元素,并对数组中的每个元素执行return语句中的操作。
希望这会有所帮助。
我以前写的解决方案有一个错误。议程组件在实际接收道具之前设置状态,并且在道具更新时未更新状态。
由于某种原因,componentWillReceiveProps从未获得任何道具。但是,componentDidUpdate在一次更新后收到了道具。问题是您在setState
中不能 componentDidUpdate()
,否则您将陷入无限循环。所以这里是一个解决方法。如果有人对此有更好的解决方案,请编辑我的答案或发布新答案。
以下内容仅适用于您的议程组件。没什么需要更新的
首先,从此更新状态声明:
state = { items:this.props.items,//使用item = {item}获取上面传递的项目,并将它们分配给Agenda组件中的状态变量items }
对此:
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
};
在您的render()
函数中更改
render(){ const {items} = this.state; //解构状态 返回( //将其放置在您要在AgendaComponent中呈现数据的位置,您说过您正在使用文本组件,因此它想要这样 items.map(item => { 返回( //假设item对象带有一个id(如果不是),则必须添加一个唯一键,以便可以调用一个可更新count变量并返回它的func {item.name} {item.date} ) }) ) } }
对此:
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>
);
}
}
很抱歉,答案很长,但我希望这是您所需要的。