From 02afd32b4ddd6066264b9be3babea2cbdd4ff636 Mon Sep 17 00:00:00 2001 From: Nathan Wenneker Date: Thu, 5 Nov 2015 18:20:32 -0700 Subject: [PATCH] Initial attempt at memoization within component. This is an example of a first stab at memoizing data transformation once you realize it is an expensive operation. Of course there are better and more generic ways to achieve this. --- containers/App.js | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/containers/App.js b/containers/App.js index 916c3a1..ec70524 100644 --- a/containers/App.js +++ b/containers/App.js @@ -6,6 +6,36 @@ import TodoList from '../components/TodoList' import Footer from '../components/Footer' class App extends Component { + + constructor(props, context) { + super(props, context); + this.lastFilter = null; + this.lastTodos = null; + this.memoizedVisibleTodos = null; + } + + componentWillReceiveProps(nextProps) { + if(nextProps.todos !== this.props.todos || nextProps.visibilityFilter !== this.props.visibilityFilter) { + this.memoizedVisibleTodos = null; + } + } + + visibleTodos() { + // If this is expensive, let's memoize it manually first. + this.memoizedVisibleTodos = this.memoizedVisibleTodos || function(todos, filter) { + console.log("Recalculating visibleTodos"); + switch (filter) { + case VisibilityFilters.SHOW_ALL: + return todos; + case VisibilityFilters.SHOW_COMPLETED: + return todos.filter(todo => todo.completed) + case VisibilityFilters.SHOW_ACTIVE: + return todos.filter(todo => !todo.completed) + } + }(this.props.todos, this.props.visibilityFilter); + return this.memoizedVisibleTodos; + } + render() { console.log(this.props); // Injected by connect() call: @@ -17,7 +47,7 @@ class App extends Component { dispatch(addTodo(text)) } /> dispatch(completeTodo(index)) } /> @@ -33,7 +63,7 @@ class App extends Component { } App.propTypes = { - visibleTodos: PropTypes.arrayOf(PropTypes.shape({ + todos: PropTypes.arrayOf(PropTypes.shape({ text: PropTypes.string.isRequired, completed: PropTypes.bool.isRequired })), @@ -44,22 +74,11 @@ App.propTypes = { ]).isRequired } -function selectTodos(todos, filter) { - switch (filter) { - case VisibilityFilters.SHOW_ALL: - return todos - case VisibilityFilters.SHOW_COMPLETED: - return todos.filter(todo => todo.completed) - case VisibilityFilters.SHOW_ACTIVE: - return todos.filter(todo => !todo.completed) - } -} - // Which props do we want to inject, given the global state? // Note: use https://github.com/faassen/reselect for better performance. function select(state) { return { - visibleTodos: selectTodos(state.todos, state.visibilityFilter), + todos: state.todos, visibilityFilter: state.visibilityFilter, currentTheme: state.currentTheme }