如何强制dom re render in react

时间:2017-08-25 08:14:58

标签: reactjs

我试图强制子组件重新渲染。我尝试了this.forceUpdate();,但它不起作用。我把console.log语句放在我的<PostList />组件中,并且它们都没有被调用 - 不是componentDidMount,也不是componentWillMount,componentWillReceiveProps,没有一个。就好像<PostList />组件永远不会被初始化一样。我确信它是,因为我知道一个事实items.count检索我的项目。这是我的渲染方法:

 render() {
        const items = this.state.posts;
        const postList = items.count > 0 ? (<PostList comingFromSearch={true} xyz={items} />) : (<div></div>)
        const navBar = <NavigationBar />
        return (
                <div><br/>{navBar}
                   <div className="container">
                     <h3>Search Results for {this.state.searchTerm}</h3>
                        <div className="row">
                            <div className="col-x-12">{postList}</div>
                        </div>
                   </div>
                </div>
            )
     }

这是我的api电话:

    retrieveSearch(term) {
        Helpers.searchWithTerm(term).then((terms) => {
                const postsWithTermsInTitle = terms.titleResults
                this.setState({posts: postsWithTermsInTitle})
                this.forceUpdate();
        }).catch((error) => {   
                console.log("error searching: " + error);
        })
   }

我应该注意,在我之前的页面上,我有另一个`组件,也许反应是使用那个而不是这个?我想强制它使用这个实例。

如果this.forceUpdate();没有重新渲染整个DOM,我该怎么做?

感谢

2 个答案:

答案 0 :(得分:1)

您的PostListNavigationBar组件可能无法更新,因为它们仅在道具更改时更新(浅层比较)。

更改数组的内部内容时,

PostList可能不会更新,因为组件将浅显比较新状态和前一个状态。浅比较一个数组将基本检查其length属性。在这种情况下不会改变。

快速解决方案

有时您需要更新List,而不更改其任何道具或列表的长度。要实现这一点,只需将prop传递给组件并继续增加它,而不是调用force update。

retrieveSearch(term) {
    Helpers.searchWithTerm(term).then((terms) => {
            const postsWithTermsInTitle = terms.titleResults
            this.setState((curState) => ({posts: postsWithTermsInTitle, refreshCycle: curState.refreshCycle+1}))
            this.forceUpdate();
    }).catch((error) => {   
            console.log("error searching: " + error);
    })

}

 render() {
     ...
     <PostList
        ...
        refreshCycle={this.state.refreshCycle}
     />
     ...
 }

正确的解决方案

正确的解决方案是提供itemRenderer,您是一个从列表中返回单个项目的函数。此函数作为prop传递给组件。

通过这种方式,您可以控制列表中的项目如何显示,而itemRenderer函数内的更改也会导致组件更新。

 itemRenderer(itemIndex) {
    return <div>{this.props.item[itemIndex]}</div>;
 }
 render() {
    ...
    <PostList
       itemRenderer={this.itemRenderer.bind(this)}
       itemsLength={items.length}
    />
    ...
 }

itemRenderer将在PostList内循环调用(长度为itemsLength)。每个循环都将传递当前迭代的索引,因此您可以知道要从函数返回的列表中的哪个项目。

通过这种方式,您还可以使列表更具可扩展性和更适应性。

您可以在列表包中检查此类解决方案的实现,例如:https://www.npmjs.com/package/react-list

答案 1 :(得分:0)

您可以通过更改组件的状态来强制重新呈现组件及其所有子组件。在构造函数中添加一个状态对象:

constructor(props) {
  super(props)
  this.state = {
    someComponentState: 'someValue'
  }
}

现在每当你这样做:

this.setState(someComponentState, 'newValue')

它将重新渲染组件及其所有子组件。

这当然假设您的组件是基于类的组件,而不是功能组件。但是,如果您的组件是一个功能组件,您可以轻松地将其转换为基于类的组件,如下所示:

class ComponentName {
    constructor() {
      // constructor code
    }
    render() {
      // render code
    }
}
export default ComponentName

了解组件级别状态与redux状态不同,但仅在组件本身内部公开。