diff --git a/common/app/redux/actions.js b/common/app/redux/actions.js index cdc221a97b..8bdfeeda6a 100644 --- a/common/app/redux/actions.js +++ b/common/app/redux/actions.js @@ -4,10 +4,18 @@ import types from './types'; // updateTitle(title: String) => Action export const updateTitle = createAction(types.updateTitle); +let id = 0; // makeToast({ type?: String, message: String, title: String }) => Action export const makeToast = createAction( types.makeToast, - toast => toast.type ? toast : (toast.type = 'info', toast) + toast => { + id += 1; + return { + ...toast, + id, + type: toast.type || 'info' + }; + } ); // fetchUser() => Action diff --git a/common/app/redux/reducer.js b/common/app/redux/reducer.js index 1aaece38f7..34520a7514 100644 --- a/common/app/redux/reducer.js +++ b/common/app/redux/reducer.js @@ -10,10 +10,7 @@ export default handleActions( [types.makeToast]: (state, { payload: toast }) => ({ ...state, - toast: { - ...toast, - id: state.toast && state.toast.id ? state.toast.id : 1 - } + toast }), [types.setUser]: (state, { payload: user }) => ({ ...state, ...user }), diff --git a/common/app/routes/Hikes/components/Hike.jsx b/common/app/routes/Hikes/components/Hike.jsx index a18c3e3181..5e147ea6e6 100644 --- a/common/app/routes/Hikes/components/Hike.jsx +++ b/common/app/routes/Hikes/components/Hike.jsx @@ -6,18 +6,15 @@ import { createSelector } from 'reselect'; import Lecture from './Lecture.jsx'; import Questions from './Questions.jsx'; import { resetHike } from '../redux/actions'; +import { getCurrentHike } from '../redux/selectors'; const mapStateToProps = createSelector( - state => state.hikesApp.hikes.entities, - state => state.hikesApp.currentHike, - state => state.hikesApp, - (hikes, currentHikeDashedName, { shouldShowQuestions }) => { - const currentHike = hikes[currentHikeDashedName]; - return { - title: currentHike ? currentHike.title : '', - shouldShowQuestions - }; - } + getCurrentHike, + state => state.hikesApp.shouldShowQuestions, + (currentHike, shouldShowQuestions) => ({ + title: currentHike ? currentHike.title : '', + shouldShowQuestions + }) ); // export plain component for testing diff --git a/common/app/routes/Hikes/components/Hikes.jsx b/common/app/routes/Hikes/components/Hikes.jsx index 7c3aa04d4a..62b097eba4 100644 --- a/common/app/routes/Hikes/components/Hikes.jsx +++ b/common/app/routes/Hikes/components/Hikes.jsx @@ -2,7 +2,7 @@ import React, { PropTypes } from 'react'; import { compose } from 'redux'; import { connect } from 'react-redux'; import { Row } from 'react-bootstrap'; -import shouldComponentUpdate from 'react-pure-render/function'; +import PureComponent from 'react-pure-render/component'; import { createSelector } from 'reselect'; // import debug from 'debug'; @@ -15,13 +15,14 @@ import contain from '../../../utils/professor-x'; // const log = debug('fcc:hikes'); const mapStateToProps = createSelector( - state => state.hikesApp.hikes, - hikes => { - if (!hikes || !hikes.entities || !hikes.results) { + state => state.hikesApp.hikes.entities, + state => state.hikesApp.hikes.results, + (hikesMap, hikesByDashedName)=> { + if (!hikesMap || !hikesByDashedName) { return { hikes: [] }; } return { - hikes: hikes.results.map(dashedName => hikes.entities[dashedName]) + hikes: hikesByDashedName.map(dashedName => hikesMap[dashedName]) }; } ); @@ -36,7 +37,7 @@ const fetchOptions = { } }; -export class Hikes extends React.Component { +export class Hikes extends PureComponent { static displayName = 'Hikes'; static propTypes = { diff --git a/common/app/routes/Hikes/components/Lecture.jsx b/common/app/routes/Hikes/components/Lecture.jsx index d0546febf8..2598766d69 100644 --- a/common/app/routes/Hikes/components/Lecture.jsx +++ b/common/app/routes/Hikes/components/Lecture.jsx @@ -6,19 +6,18 @@ import { createSelector } from 'reselect'; import debug from 'debug'; import { toggleQuestionView } from '../redux/actions'; +import { getCurrentHike } from '../redux/selectors'; const log = debug('fcc:hikes'); const mapStateToProps = createSelector( - state => state.hikesApp.hikes.entities, - state => state.hikesApp.currentHike, - (hikes, currentHikeDashedName) => { - const currentHike = hikes[currentHikeDashedName]; + getCurrentHike, + (currentHike) => { const { dashedName, description, challengeSeed: [id] = [0] - } = currentHike || {}; + } = currentHike; return { id, dashedName, diff --git a/common/app/routes/Hikes/components/Map.jsx b/common/app/routes/Hikes/components/Map.jsx index 81d77432c0..391c68693b 100644 --- a/common/app/routes/Hikes/components/Map.jsx +++ b/common/app/routes/Hikes/components/Map.jsx @@ -14,7 +14,7 @@ export default React.createClass({ hikes = [{}] } = this.props; - const vidElements = hikes.map(({ title, dashedName}) => { + const vidElements = hikes.map(({ title, dashedName }) => { return ( diff --git a/common/app/routes/Hikes/components/Questions.jsx b/common/app/routes/Hikes/components/Questions.jsx index 71d492923b..bad9d09819 100644 --- a/common/app/routes/Hikes/components/Questions.jsx +++ b/common/app/routes/Hikes/components/Questions.jsx @@ -10,8 +10,10 @@ import { releaseQuestion, grabQuestion } from '../redux/actions'; +import { getCurrentHike } from '../redux/selectors'; const answerThreshold = 100; +const springProperties = { stiffness: 120, damping: 10 }; const actionsToBind = { answerQuestion, moveQuestion, @@ -20,11 +22,10 @@ const actionsToBind = { }; const mapStateToProps = createSelector( - state => state.hikesApp.hikes.entities, - state => state.hikesApp.hikes.results, + getCurrentHike, state => state.hikesApp, state => state.app.isSignedIn, - (hikesMap, hikesByDashname, ui, isSignedIn) => { + (currentHike, ui, isSignedIn) => { const { currentQuestion = 1, mouse = [ 0, 0 ], @@ -34,7 +35,12 @@ const mapStateToProps = createSelector( shouldShakeQuestion = false } = ui; + const { + tests = [] + } = currentHike; + return { + tests, currentQuestion, isCorrect, mouse, @@ -138,7 +144,7 @@ class Question extends React.Component { render() { const { tests = [], - mouse: [x], + mouse: [xPosition], currentQuestion, shouldShakeQuestion } = this.props; @@ -158,7 +164,7 @@ class Question extends React.Component { xs={ 8 } xsOffset={ 2 }> - + { questionElement }
diff --git a/common/app/routes/Hikes/redux/selectors.js b/common/app/routes/Hikes/redux/selectors.js new file mode 100644 index 0000000000..f89651eada --- /dev/null +++ b/common/app/routes/Hikes/redux/selectors.js @@ -0,0 +1,8 @@ +// use this file for common selectors +import { createSelector } from 'reselect'; + +export const getCurrentHike = createSelector( + state => state.hikesApp.hikes.entities, + state => state.hikesApp.currentHike, + (hikesMap, currentHikeDashedName) => (hikesMap[currentHikeDashedName] || {}) +);