diff --git a/common/app/routes/challenges/components/Challenge.jsx b/common/app/routes/challenges/components/Challenge.jsx
index d4421ef7c2..331d7b426e 100644
--- a/common/app/routes/challenges/components/Challenge.jsx
+++ b/common/app/routes/challenges/components/Challenge.jsx
@@ -1,13 +1,26 @@
import React, { PropTypes } from 'react';
-
-import PureComponent from 'react-pure-render/component';
+import { connect } from 'react-redux';
import { Col } from 'react-bootstrap';
+import { createSelector } from 'reselect';
+import PureComponent from 'react-pure-render/component';
import Editor from './Editor.jsx';
import SidePanel from './Side-Panel.jsx';
import Preview from './Preview.jsx';
+import { challengeSelector } from '../redux/selectors';
-export default class extends PureComponent {
+const mapStateToProps = createSelector(
+ challengeSelector,
+ state => state.challengesApp.content,
+ ({ challenge, showPreview, mode }, content) => ({
+ content,
+ challenge,
+ showPreview,
+ mode
+ })
+);
+
+export class Challenge extends PureComponent {
static displayName = 'Challenge';
static propTypes = {
@@ -54,3 +67,5 @@ export default class extends PureComponent {
);
}
}
+
+export default connect(mapStateToProps)(Challenge);
diff --git a/common/app/routes/challenges/components/Challenges.jsx b/common/app/routes/challenges/components/Challenges.jsx
index 5f2fc05d7e..d4aaa384e1 100644
--- a/common/app/routes/challenges/components/Challenges.jsx
+++ b/common/app/routes/challenges/components/Challenges.jsx
@@ -8,35 +8,16 @@ import PureComponent from 'react-pure-render/component';
import Challenge from './Challenge.jsx';
import Step from './step/Step.jsx';
import { fetchChallenge } from '../../../redux/actions';
-import { STEP, HTML } from '../../../utils/challengeTypes';
+import { challengeSelector } from '../redux/selectors';
const bindableActions = {
fetchChallenge
};
-const challengeSelector = createSelector(
- state => state.challengesApp.challenge,
- state => state.entities.challenge,
- (challengeName, challengeMap) => {
- const challenge = challengeMap[challengeName];
- return {
- challenge: challenge,
- showPreview: !!challenge && challenge.challengeType === HTML,
- isStep: !!challenge && challenge.challengeType === STEP,
- mode: !!challenge && challenge.challengeType === HTML ?
- 'text/html' :
- 'javascript'
- };
- }
-);
-
const mapStateToProps = createSelector(
challengeSelector,
- state => state.challengesApp.content,
- (challengeProps, content) => ({
- ...challengeProps,
- content
- })
+ state => state.challengesApp.challenge,
+ ({ isStep }, challenge) => ({ challenge, isStep })
);
const fetchOptions = {
@@ -45,24 +26,19 @@ const fetchOptions = {
return [ dashedName ];
},
isPrimed({ challenge }) {
- return challenge;
+ return !!challenge;
}
};
export class Challenges extends PureComponent {
static displayName = 'Challenges';
- static propTypes = {
- challenge: PropTypes.object,
- showPreview: PropTypes.bool,
- mode: PropTypes.string,
- isStep: PropTypes.bool
- };
+ static propTypes = { isStep: PropTypes.bool };
render() {
if (this.props.isStep) {
- return ;
+ return ;
}
- return ;
+ return ;
}
}
diff --git a/common/app/routes/challenges/components/step/Step.jsx b/common/app/routes/challenges/components/step/Step.jsx
index 9941d486db..6d95f413cc 100644
--- a/common/app/routes/challenges/components/step/Step.jsx
+++ b/common/app/routes/challenges/components/step/Step.jsx
@@ -2,17 +2,20 @@ import React, { PropTypes } from 'react';
import classnames from 'classnames';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
-import { goToStep } from '../../redux/actions';
import PureComponent from 'react-pure-render/component';
import ReactTransitionReplace from 'react-css-transition-replace';
+import { goToStep } from '../../redux/actions';
+import { challengeSelector } from '../../redux/selectors';
import { Button, Col, Image, Row } from 'react-bootstrap';
const transitionTimeout = 1000;
const mapStateToProps = createSelector(
+ challengeSelector,
state => state.challengesApp.currentStep,
state => state.challengesApp.previousStep,
- (currentStep, previousStep) => ({
+ ({ challenge }, currentStep, previousStep) => ({
+ challenge,
currentStep,
previousStep,
isGoingForward: currentStep > previousStep
diff --git a/common/app/routes/challenges/redux/selectors.js b/common/app/routes/challenges/redux/selectors.js
new file mode 100644
index 0000000000..b248c64e5b
--- /dev/null
+++ b/common/app/routes/challenges/redux/selectors.js
@@ -0,0 +1,21 @@
+import { STEP, HTML } from '../../../utils/challengeTypes';
+import { createSelector } from 'reselect';
+
+export const challengeSelector = createSelector(
+ state => state.challengesApp.challenge,
+ state => state.entities.challenge,
+ (challengeName, challengeMap) => {
+ if (!challengeName || !challengeMap) {
+ return {};
+ }
+ const challenge = challengeMap[challengeName];
+ return {
+ challenge: challenge,
+ showPreview: !!challenge && challenge.challengeType === HTML,
+ isStep: !!challenge && challenge.challengeType === STEP,
+ mode: !!challenge && challenge.challengeType === HTML ?
+ 'text/html' :
+ 'javascript'
+ };
+ }
+);