From 535652d074d5d668683cc2bc41f4af4393437e42 Mon Sep 17 00:00:00 2001 From: John Furrow Date: Sun, 8 Nov 2015 21:34:05 -0800 Subject: [PATCH] Insert state into strategic components rather than entire app --- .../components/action-bar/SortDropdown.js | 19 +++- .../scripts/components/modals/Modals.js | 16 +++- .../scripts/components/sidebar/ClientStats.js | 61 ++++++++---- .../components/sidebar/StatusFilters.js | 8 ++ .../components/torrent-list/Torrent.js | 1 - client/source/scripts/containers/ActionBar.js | 12 ++- client/source/scripts/containers/App.js | 94 ++++++++++--------- client/source/scripts/containers/Sidebar.js | 8 +- .../source/scripts/containers/TorrentList.js | 36 +++++-- .../scripts/reducers/torrentsReducer.js | 38 +++++++- client/source/scripts/reducers/uiReducer.js | 39 +------- .../scripts/selectors/torrentSelector.js | 21 ++++- 12 files changed, 227 insertions(+), 126 deletions(-) diff --git a/client/source/scripts/components/action-bar/SortDropdown.js b/client/source/scripts/components/action-bar/SortDropdown.js index d05d82ee..c310ace9 100644 --- a/client/source/scripts/components/action-bar/SortDropdown.js +++ b/client/source/scripts/components/action-bar/SortDropdown.js @@ -130,10 +130,23 @@ export default class SortDropdown extends React.Component { onItemSelect(sortBy) { this.setState({ - isExpanded: false, - sortBy + isExpanded: false }); - this.props.onSortChange(sortBy); + let direction = this.props.selectedItem.direction; + + if (this.props.selectedItem.property === sortBy.property) { + direction = direction === 'asc' ? 'desc' : 'asc'; + } else { + direction = 'asc'; + } + + let sortProperty = { + displayName: sortBy.displayName, + property: sortBy.property, + direction + }; + + this.props.onSortChange(sortProperty); } render() { diff --git a/client/source/scripts/components/modals/Modals.js b/client/source/scripts/components/modals/Modals.js index 09d1fee7..2cf27459 100644 --- a/client/source/scripts/components/modals/Modals.js +++ b/client/source/scripts/components/modals/Modals.js @@ -1,15 +1,17 @@ +import { connect } from 'react-redux'; import CSSTransitionGroup from 'react-addons-css-transition-group'; import React from 'react'; import AddTorrents from './AddTorrents'; import { dismissModal } from '../../actions/UIActions'; import Icon from '../icons/Icon'; +import uiSelector from '../../selectors/uiSelector'; const methodsToBind = [ 'handleOverlayClick' ]; -export default class Modal extends React.Component { +class Modal extends React.Component { constructor() { super(); @@ -27,10 +29,18 @@ export default class Modal extends React.Component { this.props.dispatch(dismissModal()); } + shouldComponentUpdate(nextProps) { + if (nextProps.modal !== this.props.modal) { + return true; + } else { + return false; + } + } + render() { let modal = null; - switch (this.props.type) { + switch (this.props.modal) { case 'add-torrents': modal = ( @@ -103,7 +126,7 @@ export default class ClientStats extends React.Component {
+ selectedItem={this.props.torrentList.sortBy} />
@@ -73,3 +75,5 @@ export default class FilterBar extends React.Component { } } + +export default connect(uiSelector)(ActionBar); diff --git a/client/source/scripts/containers/App.js b/client/source/scripts/containers/App.js index 157fa664..776e7271 100644 --- a/client/source/scripts/containers/App.js +++ b/client/source/scripts/containers/App.js @@ -2,7 +2,6 @@ import { connect } from 'react-redux'; import React from 'react'; import ActionBar from '../containers/ActionBar'; -import { fetchTorrents, fetchTransferData } from '../actions/ClientActions'; import Modals from '../components/modals/Modals'; import Sidebar from './Sidebar'; import rootSelector from '../selectors/rootSelector'; @@ -10,13 +9,13 @@ import TorrentList from '../containers/TorrentList'; import TorrentListHeader from '../components/torrent-list/TorrentListHeader'; const methodsToBind = [ - 'componentWillMount', - 'componentWillUnmount', - 'getTransferData', - 'getTorrents' + // 'componentWillMount', + // 'componentWillUnmount', + // 'getTransferData', + // 'getTorrents' ]; -class FloodApp extends React.Component { +export default class FloodApp extends React.Component { constructor() { super(); @@ -31,54 +30,59 @@ class FloodApp extends React.Component { this[method] = this[method].bind(this); }); } - - componentWillMount() { - let getTorrents = this.getTorrents; - let getTransferData = this.getTransferData; - - this.state.torrentFetchInterval = setInterval(function() { - getTorrents(); - }, 5000); - - this.state.clientDataFetchInterval = setInterval(function() { - getTransferData(); - }, 5000); - - this.getTorrents(); - this.getTransferData(); - } - - componentWillUnmount() { - clearInterval(this.state.torrentFetchInterval); - clearInterval(this.state.clientDataFetchInterval); - } - - getTransferData() { - this.props.dispatch(fetchTransferData()); - } - - getTorrents() { - this.props.dispatch(fetchTorrents()); - } + // + // componentWillMount() { + // let getTorrents = this.getTorrents; + // let getTransferData = this.getTransferData; + // + // this.state.torrentFetchInterval = setInterval(function() { + // getTorrents(); + // }, 5000); + // + // this.state.clientDataFetchInterval = setInterval(function() { + // getTransferData(); + // }, 5000); + // + // this.getTorrents(); + // this.getTransferData(); + // } + // + // componentWillUnmount() { + // clearInterval(this.state.torrentFetchInterval); + // clearInterval(this.state.clientDataFetchInterval); + // } render() { return (
- +
- - + +
- +
); } + // render() { + // return ( + //
+ // + //
+ // + // + //
+ // + //
+ // ); + // } + } -export default connect(rootSelector)(FloodApp); +// export default connect(rootSelector)(FloodApp); diff --git a/client/source/scripts/containers/Sidebar.js b/client/source/scripts/containers/Sidebar.js index d9b3900b..1a9655a8 100644 --- a/client/source/scripts/containers/Sidebar.js +++ b/client/source/scripts/containers/Sidebar.js @@ -1,3 +1,4 @@ +import { connect } from 'react-redux'; import React from 'react'; import ClientStats from '../components/sidebar/ClientStats'; @@ -5,13 +6,14 @@ import { setTorrentsFilter, setTorrentsSearch } from '../actions/UIActions'; import StatusFilters from '../components/sidebar/StatusFilters'; import SearchBox from '../components/sidebar/SearchBox'; import UIActions from '../actions/UIActions'; +import uiSelector from '../selectors/uiSelector'; const methodsToBind = [ 'handleFilterChange', 'handleSearchChange' ]; -export default class Sidebar extends React.Component { +class Sidebar extends React.Component { constructor() { super(); @@ -35,9 +37,11 @@ export default class Sidebar extends React.Component { + activeFilter={this.props.torrentList.filterBy} /> ); } } + +export default connect(uiSelector)(Sidebar); diff --git a/client/source/scripts/containers/TorrentList.js b/client/source/scripts/containers/TorrentList.js index 0489584b..0fe7a2fe 100644 --- a/client/source/scripts/containers/TorrentList.js +++ b/client/source/scripts/containers/TorrentList.js @@ -1,9 +1,13 @@ +import { connect } from 'react-redux'; import React from 'react'; import ReactDOM from 'react-dom'; +import { fetchTorrents } from '../actions/ClientActions'; import { handleTorrentClick } from '../actions/UIActions'; import Torrent from '../components/torrent-list/Torrent'; +import torrentSelector from '../selectors/torrentSelector'; import UIActions from '../actions/UIActions'; +import uiSelector from '../selectors/uiSelector'; const methodsToBind = [ 'componentDidMount', @@ -12,25 +16,28 @@ const methodsToBind = [ 'handleTorrentClick', 'handleWindowResize', 'getListPadding', + 'getTorrents', 'getViewportLimits', 'setViewportHeight', 'shouldComponentUpdate' ]; -export default class TorrentList extends React.Component { +class TorrentList extends React.Component { constructor() { super(); this.state = { + count: 0, + maxTorrentIndex: 4, + minTorrentIndex: 0, + scrollPosition: 0, + spaceBottom: 0, + spaceTop: 0, torrentCount: 0, + torrentFetchInterval: null, torrentHeight: 64, torrentRenderBuffer: 2, - minTorrentIndex: 0, - maxTorrentIndex: 4, - spaceTop: 0, - spaceBottom: 0, - scrollPosition: 0, viewportHeight: 0 }; @@ -46,6 +53,17 @@ export default class TorrentList extends React.Component { componentWillUnmount() { window.removeEventListener('resize', this.handleWindowResize); + clearInterval(this.state.torrentFetchInterval); + } + + componentWillMount() { + let getTorrents = this.getTorrents; + + this.state.torrentFetchInterval = setInterval(function() { + getTorrents(); + }, 5000); + + getTorrents(); } shouldComponentUpdate(nextProps) { @@ -56,6 +74,10 @@ export default class TorrentList extends React.Component { } } + getTorrents() { + this.props.dispatch(fetchTorrents()); + } + handleTorrentClick(hash, event) { this.props.dispatch(handleTorrentClick({ hash, @@ -167,3 +189,5 @@ export default class TorrentList extends React.Component { } } + +export default connect(torrentSelector)(TorrentList); diff --git a/client/source/scripts/reducers/torrentsReducer.js b/client/source/scripts/reducers/torrentsReducer.js index 9af2e9f6..4aa1a281 100644 --- a/client/source/scripts/reducers/torrentsReducer.js +++ b/client/source/scripts/reducers/torrentsReducer.js @@ -1,10 +1,42 @@ -export default function torrentsReducer(state = [], action) { +import { selectTorrents } from '../util/selectTorrents'; + +const initialState = { + selectedTorrents: [], + torrents: [] +}; + +export default function torrentsReducer(state = initialState, action) { switch (action.type) { + case 'CLICK_TORRENT': + let event = action.payload.event; + let hash = action.payload.hash; + let selectedTorrents = Object.assign([], state.selectedTorrents); + let torrentList = action.payload.torrentList; + + selectedTorrents = selectTorrents({ + event, + hash, + selectedTorrents, + torrentList + }); + + return Object.assign( + {}, + state, + { + ...state, + selectedTorrents: selectedTorrents + } + ); + case 'RECEIVE_TORRENTS': return Object.assign( - [], + {}, state, - action.payload.torrents + { + ...state, + torrents: action.payload.torrents + } ); default: diff --git a/client/source/scripts/reducers/uiReducer.js b/client/source/scripts/reducers/uiReducer.js index 451107b8..9ee79c9b 100644 --- a/client/source/scripts/reducers/uiReducer.js +++ b/client/source/scripts/reducers/uiReducer.js @@ -1,5 +1,3 @@ -import { selectTorrents } from '../util/selectTorrents'; - const initialState = { fetchingData: true, modal: null, @@ -14,45 +12,10 @@ const initialState = { property: 'added' } } -} +}; export default function uiReducer(state = initialState, action) { switch (action.type) { - case 'CLICK_TORRENT': - let event = action.payload.event; - let hash = action.payload.hash; - let selectedTorrents = Object.assign([], state.torrentList.selected); - let torrentList = action.payload.torrentList; - - selectedTorrents = selectTorrents({ - event, - hash, - selectedTorrents, - torrentList - }); - - return Object.assign( - {}, - state, - { - ...state, - torrentList: { - ...state.torrentList, - selected: selectedTorrents - } - } - ); - - case 'REQUEST_TORRENTS': - return Object.assign( - {}, - state, - { - ...state, - fetchingData: true - } - ); - case 'RECEIVE_TORRENTS': return Object.assign( {}, diff --git a/client/source/scripts/selectors/torrentSelector.js b/client/source/scripts/selectors/torrentSelector.js index c4af5da6..3caf6579 100644 --- a/client/source/scripts/selectors/torrentSelector.js +++ b/client/source/scripts/selectors/torrentSelector.js @@ -9,7 +9,9 @@ const torrentListSortBy = state => state.ui.torrentList.sortBy; const torrentListFilterBy = state => state.ui.torrentList.filterBy; -const torrentList = state => state.torrents; +const selectedTorrents = state => state.torrents.selectedTorrents; + +const torrentList = state => state.torrents.torrents; const filteredTorrents = createSelector( torrentListFilterBy, @@ -27,12 +29,23 @@ const searchedTorrents = createSelector( } ); -const torrentSelector = createSelector( - torrentListSortBy, +const sortedTorrents = createSelector( searchedTorrents, - (torrentListSortBy, searchedTorrents) => { + torrentListSortBy, + (searchedTorrents, torrentListSortBy) => { return sortTorrents(searchedTorrents, torrentListSortBy); } ); +const torrentSelector = createSelector( + selectedTorrents, + sortedTorrents, + (selectedTorrents, sortedTorrents) => { + return { + selectedTorrents, + torrents: sortedTorrents + }; + } +); + export default torrentSelector;