[英]React Native - rerender child component from parent component
我正在尝试修改日历 - https://github.com/wix/react-native-calendars以便当我按下一天时,背景和文本 colors 会在那天发生变化。 我读到要重新渲染一个组件,您需要更新父组件的 state,这就是我正在尝试的:
父类.js
export default class InitiateRent extends Component {
state = {
....
this.markedDays: {},
someVar: 0
};
constructor() {
super();
this.handler = this.handler.bind(this);
this.markedDays = {};
}
....
handler(e) {
console.log('handler running');
this.setState({
someVar: 123
})
}
<Calendar
handler={this.handler}
markedDates={this.markedDays}
onDayPress={(day)=> {
console.log('selected day', day);
var dateString = `'${day.year}-${day.month}-${day.day}'`
var addDate = {
[dateString]: {
customStyles: {
container: {
backgroundColor: '#6de3dc',
},
text: {
color: 'white',
fontWeight: 'bold'
},
},
}
}
this.markedDays = Object.assign(addDate, this.markedDays);
console.log(this.markedDays);
}}
....
子.js
pressDay(date) {
this.props.handler();
this._handleDayInteraction(date, this.props.onDayPress);
}
renderDay(day, id) { //GETS CALLED IN CHILD RENDER METHOD VIA AN INTERMEDIARY
....
<DayComp
....
onPress={this.pressDay}
....
}
一切正常,除了我没有得到预期的结果 - 当我按日历上的日期时,处理程序触发, state 发生变化,并且在控制台中我的 object 看起来正确:
Object
'2018-9-23': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
'2018-9-26': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
'2018-9-28': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
'2018-9-29': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
但是日历上当天的背景没有改变,文本也没有改变——我需要做什么才能让它重新呈现(改变)?
更新
我创建了一系列处理程序,从最底层的day
组件开始,它只代表日历上的一天,一直到最高级的父视图(不是 App.js,但就在它下面),但仍然什么也没做。
更新
日历是模态的,我没有任何更新其 state 的处理程序,这可能是问题所在吗?
更新
我在文档中找到了这个:
.免责声明。 确保 markedDates 参数是不可变的。 如果您更改 markedDates object 内容但对其的引用未更改,则不会触发日历更新。
这是什么意思?
更新
我试图通过一些谷歌搜索来解释这意味着什么,这会使this.state.markedDays
不可变吗?:
const markedDays = this.state.markedDays;
var dateString = `'${day.year}-${day.month}-${day.day}'`;
var addDate = {
[dateString]: {
customStyles: {
container: {
backgroundColor: '#6de3dc',
},
text: {
color: 'white',
fontWeight: 'bold'
},
},
}
}
const markedDaysHolder = {
...markedDays,
...addDate
}
this.state.markedDays = markedDaysHolder;
更新
我放:
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("componentDidUpdate in InitiateRent:", prevProps, prevState, snapshot);
}
上面的output是:
componentDidUpdate in InitiateRent: (3) (index.bundle, line 761)
{initiateRentMessage: function, modalHeight: 200, modalWidth: 200, handler: function}
{modalVisible: true, message: "Hi, I would like to rent an item from you.", rentButtonBackground: "#6de3dc", someVar: 123, markedDays: Object}
undefined
我可以从这个 output 看到 state object markedDays
随着每次按下按钮而变大,为什么样式没有改变?
在所有相关组件中,我注意到它不会在最低阶组件上触发,这是需要更改的组件。
我也有这个问题,这是你需要做的
constructor(props) {
super(props)
this.state = {
}
this.onDayPress = this.onDayPress
}
showCalendar = () => {
return (
<Calendar
onDayPress={this.onDayPress}
style={styles.calendar}
hideExtraDays
markedDates={{
[this.state.selected]: {
selected: true,
disableTouchEvent: true,
selectedDotColor: 'orange',
},
}}
/>
)
}
onDayPress = day => {
this.setState({
selected: day.dateString,
})
}
这是我试图做的事情的冲洗答案。 我希望能够通过按下它来选择和取消选择日期(在@HaiderAli 帮助之后取消选择是问题):
我所要做的就是:
onDayPress = (day) => {
const _selectedDay = day.dateString;
let marked = true;
if (this.state._markedDates[_selectedDay]) {
// Already in marked dates, so reverse current marked state
marked = !this.state._markedDates[_selectedDay].selected;
console.log('marked:', marked);
}
// Create a new object using object property spread since it should be immutable
// Reading: https://davidwalsh.name/merge-objects
const updatedMarkedDates = {
...this.state._markedDates,
...{
[_selectedDay]: {
'selected': marked,
customStyles: {
container: {
backgroundColor: '#6de3dc',
},
text: {
color: 'white',
fontWeight: 'bold'
},
},
}
}
}
// Triggers component to render again, picking up the new state
this.setState({ _markedDates: updatedMarkedDates });
}
我添加了'selected':
,它需要在那里,这个功能改进了@HaiderAli 的答案。
为了得到取消选择工作,开node_modules/react-native-calendars/src/calendar/day/custom/index.js
(这是你的错了文件,如果你不使用markingType={'custom'}
支撑上日历。如果您不使用道具,请编辑node_modules/react-native-calendars/src/calendar/day/basic/index.js
)。 进行此更改:
....
render() {
let containerStyle = [this.style.base];
let textStyle = [this.style.text];
let marking = this.props.marking || {};
if (marking && marking.constructor === Array && marking.length) {
marking = {
marking: true
};
}
const isDisabled = typeof marking.disabled !== 'undefined' ? marking.disabled : this.props.state === 'disabled';
console.log('marking in day:', marking.selected);
if (marking.selected) {
containerStyle.push(this.style.selected);
} else if (isDisabled) {
textStyle.push(this.style.disabledText);
} else if (this.props.state === 'today') {
containerStyle.push(this.style.today);
textStyle.push(this.style.todayText);
/********ADD THIS CONDITION********/
} else if(!marking.selected) {
textStyle.push({backgroundColor: '#ffffff', color: '#2d4150'});
}
....
import { View, Text, StyleSheet } from 'react-native';
import React, { useState, useEffect } from 'react';
import { Calendar, CalendarList, Agenda } from 'react-native-calendars';
const Calender = () => {
const [selectedDay, setSelectedDay] = useState();
return (
<View style={{ flex: 1, backgroundColor: 'white' }}>
<Calendar
style={[styles.calendar, { height: 350 }]}
onDayPress={(day) => {
setSelectedDay({ selected: day.dateString });
}}
enableSwipeMonths={true}
markedDates={{
[selectedDay?.selected]: {
selected: true,
disableTouchEvent: true,
selectedDotColor: 'orange',
},
}}
/>
</View>
);
};
export default Calender;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.