[英]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.