【问题标题】:Optimizing React-Redux connected PureComponent优化 React-Redux 连接的 PureComponent
【发布时间】:2018-09-23 04:16:06
【问题描述】:

我在尝试优化我的 React-Redux 应用程序时非常沮丧。

我有一个标题组件,它会在每次更改 redux 存储时重新加载。我的头组件是 PureComponent

我已经安装了你为什么更新,它告诉我:

Header.props: Value did not change. Avoidable re-render!

这是我的组件:

export class Header extends PureComponent {

    logout() {
        // this.props.logout();
    }

    signup = () => {
        this.props.history.push(urls.SIGNUP)
    }

    render() {
        console.log("=============== RELOADING HEADER")
        return (
            <div>
                <HeaderContent 
                    logout={this.logout.bind(this)}
                    signup={this.signup.bind(this)}
                    user={this.props.user}/>                    
            </div> 
        )
    }
}

export function mapStateToProps(store) {
    // EDITTED: I initially thought this was causing the problem
    // but i get the same issue when returning a javascript object
    //const u = loginUserFactory(store);
    const u ={}
    return {
        user: u,
    }
}

export function mapDispatchToProps(dispatch) {
    return {
        logout: function l() {
            dispatch(authActions.logout())
        }
    }
}

export function mergeProps(propsFromState,propsFromDispatch,ownProps) {
    return {
        // logout: function logout() {
        //     propsFromDispatch.logout()
        // },
        ...propsFromState,
        ...ownProps
    }
}

let HeaderContainer = connect(
    mapStateToProps,
    mapDispatchToProps,
    mergeProps,
    {pure: true}
)(Header)

export default withRouter(HeaderContainer);

Header.propTypes = {
    history: PropTypes.object.isRequired,
    user: PropTypes.object.isRequired,
    logout: PropTypes.func.isRequired,
}

我已验证每次更改 redux 存储时都会打印指示调用渲染函数的 console.log。

如果我取消注释合并道具中的函数,为什么DidYouUpdate 抱怨该函数导致重新渲染。

重新渲染显着影响了我的应用的性能。我考虑编写自己的 shouldComponentUpdate() 函数,但读到出于性能原因,在该函数中执行深度等于是一个坏主意。

那我该怎么办?

编辑:

这是登录用户工厂中的代码。最初我认为这是问题所在,但当我删除该代码时,我仍然遇到同样的问题。

const loginUserFactory = state => {
    const u = getLoginUser(state);
    const isLoggedIn = !_.isEmpty(u);
    const location = getLocation(state);
    return {
        get id() { return u.id },
        get groupNames() { return u.group_names },
        get avatarSmall() { return u.avatar_small },
        get name() { return u.name },
        get email() { return u.email },

        // my goal was to localize these methods into one file 
        // to avoid repeated code and 
        // to make potential refactoring easier 
        get location() { return location},
        get isHost() {return u.type === "host"},
        get isBooker() {return u.type === "booker"},
        get isLoggedIn() { return isLoggedIn },
    }
}

export default loginUserFactory;

【问题讨论】:

  • 您仍在创建新的用户对象。每次调用 mapStateToProps 时,const u = {} 都会创建一个新的空对象(在 每个 对商店的更改上)。 {} 不是单身人士。它创建一个新对象。您需要将用户存储在您的商店对象中并从那里获取它。这就是为什么mapStateToProps 将 store 作为参数 -> 以实际从中获取一些东西。

标签: javascript reactjs performance optimization redux


【解决方案1】:

我猜loginUserFactory() 每次调用它都会创建一个新的用户对象,也就是每次更新商店时,因此总是将一个新的用户对象传递给你的组件,它不等于前一个。

此外,您的Header 不会对用户做任何事情,只是将它传递到树的下方。相反,您应该连接 HeaderContent 组件,并且只将用户对象的属性映射到它,它实际上需要,例如name

一般mapStateToProps() 不应该有任何副作用。它应该只过滤/排序/计算给定状态和自己的道具的连接组件的道具。在最简单的情况下,它只是从商店返回属性的子集。

【讨论】:

  • 有没有办法创建一个不会导致每次更新的用户对象?
  • @user1795370 我认为更好的解决方案是每次更新商店中的任何内容时都不创建用户对象。它应该在用户登录时完成一次,然后保持同一个对象。
  • @user1795370 能否提供loginUserFactory() 的代码,以便我们查看它的作用?
  • 我明白为什么我做错了。在某些情况下,拥有一个对象真的很有帮助,因为我想将一些与对象关联的方法保存在一个文件中。有更好的方法吗?
  • @user1795370 是的,此方法返回一个新的用户对象。您可以通过仅在用户登录时仅创建该对象一次来避免这种情况,该对象仅从您的商店映射该对象。一般来说mapStateToProps应该不会有任何副作用。
【解决方案2】:

您在点击处理程序中使用bind。大禁忌!当您在处理程序中绑定时,每次重新渲染都会创建一个全新的函数实例。 bind 中的 constructor 或将您的点击处理程序方法转换为箭头函数。

handleClick = () => {
}

// or

constructor() {
  super()
  this.handleClick = this.handleClick.bind(this)
}

另外,不要在mapStateToPropsmapDispatchToProps 中实施任何操作或算法。这些也会触发重新渲染。将该逻辑放在其他地方。

【讨论】:

  • 好的,我在我的代码中更改了它,但我仍然遇到同样的问题
  • 您从mapStateToProps 中删除了逻辑并将您的点击处理程序绑定为不创建自己的新实例但仍然存在性能问题?检查火焰图,看看您是否在其他地方遇到问题。 marmelab.com/blog/2017/02/06/react-is-slow-react-is-fast.html
猜你喜欢
  • 2019-11-22
  • 2018-03-23
  • 1970-01-01
  • 2018-12-27
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2018-03-19
相关资源
最近更新 更多