React Native——子事件处理程序更新父状态后,Child 中的 .Map() 项不会重新呈现
React Native -- .Map() items in Child won't rerender after Child event handler updates Parent's state
在我的项目中,在使用 .map()
函数遍历数据文件时,我将一个函数 (updatestate
) 从父组件 App
传递到Child,Main
,允许 Child 调用 .setState()
并附加到 Parent 状态的数组。
但是,当我调用这个函数来设置父级的状态时,映射部分 -- {contents}
-- 除非我再次点击屏幕,否则不会重新呈现。
有什么想法吗?我是否缺少某些绑定或需要执行一些 componentDidMount 或其他操作?我已经尝试在 eventHandler 中添加 this.forceUpdate()
但 **映射的 {contents}
部分 ** 仍然不会自动呈现。
const RootStack = StackNavigator(
{
Main: {
screen: Main}
}
);
export default class App extends Component<{}> {
constructor(props) {
super(props);
this.state = {
favoritesList: []
};
}
updateArr=(itemname, url)=>{this.setState({ favoritesList: [...this.state.favoritesList, {"item_name":itemname, "url":url}]})};
render() {
return <RootStack screenProps={{appstate: this.state,
updatestate: this.updateArr}}
/>;
}
}
class Main extends React.Component {
render() {
var updatestate = this.props.screenProps.updatestate;
//collection is the data (local JSON) i'm looping thru via .map in Main Component
const contents = collection.map((item, index) => {
return (
<Card key={index}
onSwipedRight={() => {updatestate(item.item_name,item.url)}}
>
<View> //THIS and anything after <Card> doesn't render for the next card automatically if I do 'onSwipedRight'
<Image
source={{uri: item.url}} />
</View>
</Card>
)
},this);
return (
<View>
<CardStack>
{contents} //THIS IS THE PART THAT WON'T AUTO-RERENDER AFTER THE EVENT HANDLER THAT SETS THE PARENT'S STATE
</CardStack>
</View>
);
}
}
为了确保这不是事件处理程序的问题,我添加了一个不设置父级状态的函数,并让 <Card>
在事件处理程序上调用它 - 它有效完美,子组件 <Card>
呈现完美。似乎是 updatestate
从父级传递给子级的函数调用 .setState()
上游,由于某种原因导致子级无法 render/not 完成渲染 在事件处理程序之后映射{contents}
。
class Main extends React.Component {
render() {
var updatestate = this.props.screenProps.updatestate;
var newfunc = (a, b) => {console.log('a:', a, 'b:', b)};
const contents = collection.map((item, index) => {
return (
<Card key={index}
newfunc(item.item_name,item.item_name);}}
// onSwipedRight={() => {updatestate(item.item_name,item.url); }}
>
尝试像这样重写你的 setState
import { InteractionManager } from "react-native";
updateArr = (itemname, url) => {
InteractionManager.runAfterInteractions(() => {
this.setState( prevState => ({
favoritesList: [...prevState.favoritesList, { "item_name":itemname, "url":url } ]
});
});
}
// add this line to your parent component constructor()
this.updateArr = this.updateArr.bind(this);
此外,我建议您将 React.Component 更改为 React.PureComponent 而不是它会为您处理状态更改的浅层相等并提高性能。
供参考
尽量不要将 index
用作 key
。有意义的键值有助于引擎找出需要重绘的内容。
对于你的情况,我建议首先 key={item.url}
。
https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
在我的项目中,在使用 .map()
函数遍历数据文件时,我将一个函数 (updatestate
) 从父组件 App
传递到Child,Main
,允许 Child 调用 .setState()
并附加到 Parent 状态的数组。
但是,当我调用这个函数来设置父级的状态时,映射部分 -- {contents}
-- 除非我再次点击屏幕,否则不会重新呈现。
有什么想法吗?我是否缺少某些绑定或需要执行一些 componentDidMount 或其他操作?我已经尝试在 eventHandler 中添加 this.forceUpdate()
但 **映射的 {contents}
部分 ** 仍然不会自动呈现。
const RootStack = StackNavigator(
{
Main: {
screen: Main}
}
);
export default class App extends Component<{}> {
constructor(props) {
super(props);
this.state = {
favoritesList: []
};
}
updateArr=(itemname, url)=>{this.setState({ favoritesList: [...this.state.favoritesList, {"item_name":itemname, "url":url}]})};
render() {
return <RootStack screenProps={{appstate: this.state,
updatestate: this.updateArr}}
/>;
}
}
class Main extends React.Component {
render() {
var updatestate = this.props.screenProps.updatestate;
//collection is the data (local JSON) i'm looping thru via .map in Main Component
const contents = collection.map((item, index) => {
return (
<Card key={index}
onSwipedRight={() => {updatestate(item.item_name,item.url)}}
>
<View> //THIS and anything after <Card> doesn't render for the next card automatically if I do 'onSwipedRight'
<Image
source={{uri: item.url}} />
</View>
</Card>
)
},this);
return (
<View>
<CardStack>
{contents} //THIS IS THE PART THAT WON'T AUTO-RERENDER AFTER THE EVENT HANDLER THAT SETS THE PARENT'S STATE
</CardStack>
</View>
);
}
}
为了确保这不是事件处理程序的问题,我添加了一个不设置父级状态的函数,并让 <Card>
在事件处理程序上调用它 - 它有效完美,子组件 <Card>
呈现完美。似乎是 updatestate
从父级传递给子级的函数调用 .setState()
上游,由于某种原因导致子级无法 render/not 完成渲染 在事件处理程序之后映射{contents}
。
class Main extends React.Component {
render() {
var updatestate = this.props.screenProps.updatestate;
var newfunc = (a, b) => {console.log('a:', a, 'b:', b)};
const contents = collection.map((item, index) => {
return (
<Card key={index}
newfunc(item.item_name,item.item_name);}}
// onSwipedRight={() => {updatestate(item.item_name,item.url); }}
>
尝试像这样重写你的 setState
import { InteractionManager } from "react-native";
updateArr = (itemname, url) => {
InteractionManager.runAfterInteractions(() => {
this.setState( prevState => ({
favoritesList: [...prevState.favoritesList, { "item_name":itemname, "url":url } ]
});
});
}
// add this line to your parent component constructor()
this.updateArr = this.updateArr.bind(this);
此外,我建议您将 React.Component 更改为 React.PureComponent 而不是它会为您处理状态更改的浅层相等并提高性能。
供参考
尽量不要将 index
用作 key
。有意义的键值有助于引擎找出需要重绘的内容。
对于你的情况,我建议首先 key={item.url}
。
https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318