设置状态后渲染组件不更新

Posted

技术标签:

【中文标题】设置状态后渲染组件不更新【英文标题】:Render component not update after setstate 【发布时间】:2019-02-18 16:44:46 【问题描述】:

我有一个这样的组件:

... imports

class ChooseGenres extends Component 

    constructor(props) 
        super(props);

        this.setState(
            event:  ... , genres: [] ,
            genres: [..., ..., ...]
        );
    

    eventHasGenre(item, genre_id) 
        return item.genres.indexOf(genre_id) > -1 ? true : false;
    

    onGenreChange(genre_id) 
        let event = this.state.event;

        if (this.eventHasGenre(event, genre_id)) 
            event.genres.splice(indexOf, 1)
         else 
            event.genres.push(genre_id);
        

        this.setState(
            event: event
        );
    

    render() 
        return (
            <Container>
                <Content>
                    <List dataArray=this.state.genres
                        renderRow=(item) =>
                            <ListItem onPress=this.onGenreChange.bind(this, item.id)>
                                <Body>
                                    <Text>item.name</Text>
                                </Body>
                                this.eventHasGenre(this.state.event, item.id) &&
                                    <Right>
                                        <Icon active name="arrow-forward" />
                                    </Right>
                                
                            </ListItem>
                        >
                    </List>
                </Content>
            </Container>


ChooseGenres.propTypes = 
    isLoggedIn: PropTypes.bool.isRequired,


const mapStateToProps = (state) => 
    return 
        isLoggedIn: state.isLoggedIn
    ;
;

const mapDispatchToProps = (dispatch) => (
    startup: () => dispatch(StartupActions.startup())
);

export default connect(mapStateToProps, mapDispatchToProps)(ChooseGenres);

当我单击 ListItem 时,我将流派添加到 event.genres 数组中,并且我希望显示图标。 但是即使状态中的事件对象被正确更新(我在控制台中记录它),图标仍然没有显示。

我注意到的奇怪行为是,如果我返回导航并返回此组件,图标会正确显示。

【问题讨论】:

渲染的返回是否需要右括号? 【参考方案1】:

首先你不需要在构造函数中做setState,因为它没有用,因为组件还没有被渲染

其次,您正试图改变 onGenreChange 函数中的状态。 events 对象 内不需要额外的冗余 genres 数组,只需另一个标签即可

state = 
  genres: [id: 1, name: 1, id: 2, name: 2, id: 3, name: 3]




onGenreChange = (id) => 
    const genres = this.state.genres.map(genre => 
      if (genre.id === id) 
        return ...genre, active: !genre.active
      
      return genre
    )
    this.setState(
      genres
    );
  

<List dataArray=this.state.genres
      renderRow=(item) =>
        <ListItem onPress=() => this.onGenreChange(item.id)>
          <Body>
            <Text>item.name</Text>
           </Body>
           item.active &&
             <Right>
               <Icon active name="arrow-forward" size=20 color='red'/>
              </Right>
           
         </ListItem>
        >
</List>

【讨论】:

正如我对@Sterling Beason 帖子的评论,这不是我所需要的,但你也让我明白我做错了什么。谢谢。 如果你直接改变状态对象,那么它不会重新渲染受该状态影响的dom树部分【参考方案2】:

你正在渲染:

this.state.genres

但设置状态:

this.state.event.genres

尝试将您的渲染函数更新为:

render() 
    return (
        <Container>
            <Content>
                <List dataArray=this.state.event.genres
                    renderRow=(item) =>
                        <ListItem onPress=this.onGenreChange.bind(this, item.id)>
                            <Body>
                                <Text>item.name</Text>
                            </Body>
                            this.eventHasGenre(this.state.event, item.id) &&
                                <Right>
                                    <Icon active name="arrow-forward" />
                                </Right>
                            
                        </ListItem>
                    >
                </List>
            </Content>
        </Container>

【讨论】:

你说得对。即使这不是我需要的,我明白了,你让我理解。我认为更改状态会导致所有组件重新渲染。

以上是关于设置状态后渲染组件不更新的主要内容,如果未能解决你的问题,请参考以下文章

调用 setState 后 ReactJS 元素未更新

更新状态后组件不会重新渲染

React 组件表在更新状态后被多次渲染或复制

在孩子收到道具后设置状态?

React 功能组件在状态更改后不更新

Vue 怎么缓存当前的组件?缓存后怎么更新?说说你对keep-alive的理解是啥