React Native - 从父组件重新渲染子组件
Posted
技术标签:
【中文标题】React Native - 从父组件重新渲染子组件【英文标题】:React Native - rerender child component from parent component 【发布时间】:2019-02-26 03:18:40 【问题描述】:我正在尝试修改日历 - https://github.com/wix/react-native-calendars,以便当我按下某一天时,该天的背景和文本颜色会发生变化。我读到要重新渲染一个组件,您需要更新父组件的状态,这就是我正在尝试的:
父.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);
....
Child.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
....
一切正常,除了我没有得到预期的结果 - 当我在日历上按下一个日期时,处理程序触发,状态发生变化,并且在控制台中我的对象看起来正确:
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,但就在它下面)和仍然什么也没做。
更新
日历在模式上,我没有任何处理程序来更新它的状态,这可能是问题吗?
更新
我在文档中找到了这个:
!免责声明!确保markedDates 参数是不可变的。如果你 更改markedDates 对象的内容,但对它的引用没有 不会触发更改日历更新。
这是什么意思?
更新
我试图用一些谷歌搜索来解释这意味着什么,这是否使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);
上面的输出是:
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
我可以看到状态对象markedDays
在此输出中每按一次按钮就变大,为什么样式没有改变?
在所有相关组件中,我注意到它不会在最低阶组件上触发,这是需要更改的组件。
【问题讨论】:
你不应该做这样的事情 this.state.markedDays = mappedDaysHolder.始终使用 setState 来更新状态对象。使用 setState 重新渲染组件和所有子组件。 感谢好收获,我做出了改变,但没有运气,用我发现的其他东西更新我的问题 使用 React.PureComponent 并在构造函数 constructor() super(); 中定义你的状态this.state = .... this.markedDays: , someVar: 0 ; this.handler = this.handler.bind(this); this.markedDays = ; 你的意思是this.state = .... this.markedDays:
?你的意思是this.state = .... markedDays:
?还是我应该在该州使用它?
构造函数() super(); this.state = defineStateVariablesHere: true
【参考方案1】:
我也有这个问题,这是你需要做的
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,
)
【讨论】:
【参考方案2】:这是我试图做的事情的冲洗答案。我希望能够通过按下日期来选择和取消选择日期(在@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');
....
【讨论】:
以上是关于React Native - 从父组件重新渲染子组件的主要内容,如果未能解决你的问题,请参考以下文章
为啥组件在状态更改后不重新渲染。在 react-native 函数组件中
如何使用 redux 让根组件在 react-native 中重新渲染(开源项目)