2016-04-27 72 views
2

我正在学习redux并作出反应。我决定运行一个简单的“压力测试”,让我们说15k行的生成组件(我希望我做对了)。React redux生成的无状态组件性能

所以我有无国籍的组件接收共同的道具,例如'年'。我想克隆9000多次无状态组件并更新它们。例如,将其从2016年更改为2015年的道具(年)。

我在我的测试项目中构建了这个组件,它工作正常,但响应速度慢,特别是在IE 11中。我是新来的反应+ redux,也许我做了一些事情在我的代码错误。

正如不和谐聊天室的建议我已经加入到我的网页组件:

 

    shouldComponentUpdate(nProps, nState) { 
     return nProps.year != this.props.year; 
     } 

这确实有点帮助。但它仍然很慢。

同样作为相关的问题 - 可以使用lodash.assign()来更新我的状态吗? 另外我使用的是打字稿,它似乎没有为Object.assign()内置的polyfill;这就是为什么我决定尝试点赞。

因此,这里是我的首要基础组件app.tsx:

import * as React from 'react'; 
import {bindActionCreators} from 'redux'; 
import {connect} from 'react-redux'; 
import * as pageActions from '../actions/page'; 

import User from '../components/user/User'; 
import Page from '../components/page/Page'; 

class App extends React.Component<any, any> { 

    render() { 
    const { user, page } = this.props; 
    const { setYear } = this.props.pageActions; 

    return (
     <div> 
     <User name={user.name} /> 
     <Page photos={page.photos} year={page.year} setYear={setYear} /> 
     </div> 
    ); 
    }; 
} 

function mapStateToProps (state) { 
    return { 
    user: state.user, // (1) 
    page: state.page // (2) 
    }; 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    pageActions: bindActionCreators(pageActions, dispatch) 
    }; 
} 

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

这是我第减速机:

import {assign} from 'lodash'; 


const INITIAL_STATE = { 
    year: 2016, 
    photos: [] 
}; 

function pageReducer(state = INITIAL_STATE, 
         action = {type: '', payload: null}) { 
    switch (action.type) { 
    case 'SET_YEAR': 

    return assign({}, state, {year: action.payload}); 
    default: 
     return state; 
    } 
} 

export default pageReducer; 

和页面组件:

import * as React from 'react'; 
import {range} from 'lodash'; 

let StatelessSpan: React.StatelessComponent<any> = (props) => (
    <span>{props.year} </span> 
); 

class Page extends React.Component<any, any> { 

    constructor(props) { 
    super(props); 
    } 

    private onYearBtnClick = (e) => { 
    this.props.setYear(+e.target.innerText); 
    }; 
    shouldComponentUpdate(nProps, nState) { 
    return nProps.year != this.props.year; 
    } 

    render() { 
    const {year, photos} = this.props; 

    let years = range(15000).map((value, index) => { 
     if(index % 4===0){ 
     return <StatelessSpan key={index} year={year} />; 
     } 
     return <span key={index}>i am empty</span> 
    }); 

    return <div> 
     <p> 
     <button onClick={this.onYearBtnClick}>2016</button> 
     <button onClick={this.onYearBtnClick}>2015</button> 
     <button onClick={this.onYearBtnClick}>2014</button> 
     </p> 
     {years} 
    </div>; 
    }; 
} 

export default Page; 

人告诉我innerText是实验性的和非稳定的,所以我将它改为textContent。在IE中仍然有延迟。

+0

恕我直言,这个练习听起来是任意的和不切实际的。是什么让你选择15k行?你会考虑什么样的响应水平_好?也许尝试[Chrome JS分析](https://developer.chrome.com/devtools/docs/cpu-profiling)来确定性能瓶颈。 – adamb

+0

它可能听起来是随意的,但我有一个真正的角度应用,当它可能在Dom中有200个和更多元素并且可以接收相同的道具时,而不是像这个例子中的一个道具,但是10个道具或更多。我认为,响应能力水平低于50毫秒。 – truedrog

+0

如果使用不同的Object.assign实现替换lodash的赋值函数,会发生什么情况?你有没有试过https://www.npmjs.com/package/object-assign? – matthewmatician

回答

1

React/Redux可能是编写应用程序的最佳方式,但重要的是要理解优雅有时会以性能问题为代价。幸运的是,采取优雅的解决方案并使其性能优于其他方法要容易得多。

我可以为你的React和Redux抛出一堆性能优化技巧,但你可能会优化错误的东西。您需要分析您的应用,并找出您遇到的性能问题。

您可能会觉得这段对话非常有帮助:https://www.youtube.com/watch?v=5sETJs2_jwo。 Netflix已经能够以非常缓慢的React开始,并且真正让事情变得超快速而不会让事情变得糟糕。

+0

好吧,我没有600mhz的单核心设备,我应该改述我的问题。 在更新10k简单跨度文本时,预计会出现滞后性能,而没有任何逻辑IN反应?我在纯js中构建了相同的测试,瓶颈是渲染和重新渲染。 现在,当我在React中做同样的事情时,我的分析器显示我的反应是做一些缓慢的事情(更新虚拟DOM可能?)。 那么,用这种方式来测试反应是否值钱? – truedrog

+0

如果您希望我可以仔细查看您的代码。随意给我一个完整的例子,我会尽我所能去看看我是否可以多做点事情。 – matthewmatician