@@ -21,7 +37,5 @@ export default function AddTodo({ text, updateText, addTodo }) {
}
AddTodo.propTypes = {
- text: PropTypes.string.isRequired,
- updateText: PropTypes.func.isRequired,
addTodo: PropTypes.func.isRequired,
};
diff --git a/client/components/molecules/AddTodo/AddTodoContainer.js b/client/components/molecules/AddTodo/AddTodoContainer.js
deleted file mode 100644
index 9df9bc2..0000000
--- a/client/components/molecules/AddTodo/AddTodoContainer.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-
-import AddTodo from './AddTodo';
-
-export default class AddTodoContainer extends Component {
- static propTypes = {
- addTodo: PropTypes.func.isRequired,
- };
-
- state = {
- text: '',
- }
-
- componentDidMount() {
- window.addEventListener('keypress', this.keypress);
- }
-
- componentWillUnmount() {
- window.removeEventListener('keypress', this.keypress);
- }
-
- updateText = e => this.setState({ text: e.target.value })
-
- keypress = e => {
- if (e.key === 'Enter') {
- this.addTodo();
- }
- }
-
- addTodo = () => {
- const { text } = this.state;
-
- if (text) {
- this.props.addTodo(text);
- this.setState({ text: '' });
- }
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/molecules/AddTodo/index.js b/client/components/molecules/AddTodo/index.js
index 867df2a..a08d305 100644
--- a/client/components/molecules/AddTodo/index.js
+++ b/client/components/molecules/AddTodo/index.js
@@ -1,7 +1,7 @@
import * as R from 'ramda';
import { connect } from 'react-redux';
import { attemptAddTodo } from '_thunks/todos';
-import AddTodoContainer from './AddTodoContainer';
+import AddTodo from './AddTodo';
const mapStateToProps = R.pick([]);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
addTodo: text => dispatch(attemptAddTodo(text)),
});
-export default connect(mapStateToProps, mapDispatchToProps)(AddTodoContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(AddTodo);
diff --git a/client/components/organisms/SettingsMenu/SettingsMenu.js b/client/components/organisms/SettingsMenu/SettingsMenu.js
index 0a37342..f05a01c 100644
--- a/client/components/organisms/SettingsMenu/SettingsMenu.js
+++ b/client/components/organisms/SettingsMenu/SettingsMenu.js
@@ -2,9 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
+import R from '_utils/ramda';
-export default function SettingsMenu(props) {
- const { pathname, logout } = props;
+export default function SettingsMenu({ pathname, attemptLogout }) {
+ const logout = () =>
+ attemptLogout()
+ .catch(R.identity);
const profileClasses = classNames({
'is-active': pathname.includes('profile') || pathname === '/settings' || pathname === '/settings/',
@@ -45,5 +48,5 @@ export default function SettingsMenu(props) {
SettingsMenu.propTypes = {
pathname: PropTypes.string.isRequired,
- logout: PropTypes.func.isRequired,
+ attemptLogout: PropTypes.func.isRequired,
};
diff --git a/client/components/organisms/SettingsMenu/SettingsMenuContainer.js b/client/components/organisms/SettingsMenu/SettingsMenuContainer.js
deleted file mode 100644
index 6dae495..0000000
--- a/client/components/organisms/SettingsMenu/SettingsMenuContainer.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-
-import SettingsMenu from './SettingsMenu';
-
-export default class SettingsMenuContainer extends Component {
- static propTypes = {
- pathname: PropTypes.string.isRequired,
- attemptLogout: PropTypes.func.isRequired,
- };
-
- logout = () => {
- this.props.attemptLogout()
- .catch(R.identity);
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/organisms/SettingsMenu/index.js b/client/components/organisms/SettingsMenu/index.js
index 1f64885..c0d6a10 100644
--- a/client/components/organisms/SettingsMenu/index.js
+++ b/client/components/organisms/SettingsMenu/index.js
@@ -1,7 +1,7 @@
import R from '_utils/ramda';
import { connect } from 'react-redux';
import { attemptLogout } from '_thunks/auth';
-import SettingsMenuContainer from './SettingsMenuContainer';
+import SettingsMenu from './SettingsMenu';
const mapStateToProps = R.pick([]);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
attemptLogout: () => dispatch(attemptLogout()),
});
-export default connect(mapStateToProps, mapDispatchToProps)(SettingsMenuContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(SettingsMenu);
diff --git a/client/components/pages/HomePage/HomePage.js b/client/components/pages/HomePage/HomePage.js
index 8dc46df..0ee9290 100644
--- a/client/components/pages/HomePage/HomePage.js
+++ b/client/components/pages/HomePage/HomePage.js
@@ -1,6 +1,14 @@
-import React from 'react';
+import React, { useEffect } from 'react';
+import PropTypes from 'prop-types';
+import R from '_utils/ramda';
+
+export default function HomePage({ user, pushToLogin }) {
+ useEffect(() => {
+ if (R.isEmpty(user)) {
+ pushToLogin();
+ }
+ }, []);
-export default function HomePage() {
return (
@@ -13,3 +21,8 @@ export default function HomePage() {
);
}
+
+HomePage.propTypes = {
+ user: PropTypes.shape({}).isRequired,
+ pushToLogin: PropTypes.func.isRequired,
+};
diff --git a/client/components/pages/HomePage/HomePageContainer.js b/client/components/pages/HomePage/HomePageContainer.js
deleted file mode 100644
index 5b52a80..0000000
--- a/client/components/pages/HomePage/HomePageContainer.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-import HomePage from './HomePage';
-
-export default class HomePageContainer extends Component {
- static propTypes = {
- user: PropTypes.shape({}).isRequired,
- pushToLogin: PropTypes.func.isRequired,
- }
-
- componentDidMount() {
- const { user, pushToLogin } = this.props;
- if (R.isEmpty(user)) {
- pushToLogin();
- }
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/pages/HomePage/index.js b/client/components/pages/HomePage/index.js
index 9cf5870..88ad244 100644
--- a/client/components/pages/HomePage/index.js
+++ b/client/components/pages/HomePage/index.js
@@ -1,7 +1,7 @@
import R from '_utils/ramda';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
-import HomePageContainer from './HomePageContainer';
+import HomePage from './HomePage';
const mapStateToProps = R.pick(['user']);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
pushToLogin: () => dispatch(push('/login')),
});
-export default connect(mapStateToProps, mapDispatchToProps)(HomePageContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(HomePage);
diff --git a/client/components/pages/LoginPage/LoginPage.js b/client/components/pages/LoginPage/LoginPage.js
index 88d9842..a209648 100644
--- a/client/components/pages/LoginPage/LoginPage.js
+++ b/client/components/pages/LoginPage/LoginPage.js
@@ -1,10 +1,23 @@
-import React from 'react';
+import React, { useEffect } from 'react';
+import PropTypes from 'prop-types';
+import R from '_utils/ramda';
import LoginSection from '_templates/LoginSection';
-export default function LoginPage() {
+export default function LoginPage({ user, pushToHome }) {
+ useEffect(() => {
+ if (!R.isEmpty(user)) {
+ pushToHome();
+ }
+ }, []);
+
return (
);
}
+
+LoginPage.propTypes = {
+ user: PropTypes.shape({}).isRequired,
+ pushToHome: PropTypes.func.isRequired,
+};
diff --git a/client/components/pages/LoginPage/LoginPageContainer.js b/client/components/pages/LoginPage/LoginPageContainer.js
deleted file mode 100644
index cd38fa8..0000000
--- a/client/components/pages/LoginPage/LoginPageContainer.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-import LoginPage from './LoginPage';
-
-export default class LoginPageContainer extends Component {
- static propTypes = {
- user: PropTypes.shape({}).isRequired,
- pushToHome: PropTypes.func.isRequired,
- }
-
- componentDidMount() {
- const { user, pushToHome } = this.props;
- if (!R.isEmpty(user)) {
- pushToHome();
- }
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/pages/LoginPage/index.js b/client/components/pages/LoginPage/index.js
index 7eafbc1..360008e 100644
--- a/client/components/pages/LoginPage/index.js
+++ b/client/components/pages/LoginPage/index.js
@@ -1,7 +1,7 @@
import R from '_utils/ramda';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
-import LoginPageContainer from './LoginPageContainer';
+import LoginPage from './LoginPage';
const mapStateToProps = R.pick(['user']);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
pushToHome: () => dispatch(push('/home')),
});
-export default connect(mapStateToProps, mapDispatchToProps)(LoginPageContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(LoginPage);
diff --git a/client/components/pages/RegisterPage/RegisterPage.js b/client/components/pages/RegisterPage/RegisterPage.js
index fc61301..ee17495 100644
--- a/client/components/pages/RegisterPage/RegisterPage.js
+++ b/client/components/pages/RegisterPage/RegisterPage.js
@@ -1,10 +1,23 @@
-import React from 'react';
+import React, { useEffect } from 'react';
+import PropTypes from 'prop-types';
+import R from '_utils/ramda';
import Register from '_templates/RegisterSection';
-export default function RegisterPage() {
+export default function RegisterPage({ user, pushToHome }) {
+ useEffect(() => {
+ if (!R.isEmpty(user)) {
+ pushToHome();
+ }
+ }, []);
+
return (
);
}
+
+RegisterPage.propTypes = {
+ user: PropTypes.shape({}).isRequired,
+ pushToHome: PropTypes.func.isRequired,
+};
diff --git a/client/components/pages/RegisterPage/RegisterPageContainer.js b/client/components/pages/RegisterPage/RegisterPageContainer.js
deleted file mode 100644
index 4908bc3..0000000
--- a/client/components/pages/RegisterPage/RegisterPageContainer.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-import RegisterPage from './RegisterPage';
-
-export default class RegisterPageContainer extends Component {
- static propTypes = {
- user: PropTypes.shape({}).isRequired,
- pushToHome: PropTypes.func.isRequired,
- }
-
- componentDidMount() {
- const { user, pushToHome } = this.props;
- if (!R.isEmpty(user)) {
- pushToHome();
- }
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/pages/RegisterPage/index.js b/client/components/pages/RegisterPage/index.js
index ac5f8a3..aac7a9b 100644
--- a/client/components/pages/RegisterPage/index.js
+++ b/client/components/pages/RegisterPage/index.js
@@ -1,7 +1,7 @@
import R from '_utils/ramda';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
-import RegisterPageContainer from './RegisterPageContainer';
+import RegisterPage from './RegisterPage';
const mapStateToProps = R.pick(['user']);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
pushToHome: () => dispatch(push('/home')),
});
-export default connect(mapStateToProps, mapDispatchToProps)(RegisterPageContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(RegisterPage);
diff --git a/client/components/pages/SettingsPage/SettingsPage.js b/client/components/pages/SettingsPage/SettingsPage.js
index 453836a..6356624 100644
--- a/client/components/pages/SettingsPage/SettingsPage.js
+++ b/client/components/pages/SettingsPage/SettingsPage.js
@@ -1,4 +1,5 @@
-import React from 'react';
+import React, { useEffect } from 'react';
+import R from '_utils/ramda';
import PropTypes from 'prop-types';
import { Switch, Route } from 'react-router';
@@ -6,8 +7,12 @@ import ProfileSettings from '_templates/ProfileSettings';
import AccountSettings from '_templates/AccountSettings';
import SettingsMenu from '_organisms/SettingsMenu';
-export default function SettingsPage(props) {
- const { location } = props;
+export default function SettingsPage({ user, pushToLogin, location }) {
+ useEffect(() => {
+ if (R.isEmpty(user)) {
+ pushToLogin();
+ }
+ }, []);
return (
@@ -32,6 +37,8 @@ export default function SettingsPage(props) {
}
SettingsPage.propTypes = {
+ user: PropTypes.shape({}).isRequired,
+ pushToLogin: PropTypes.func.isRequired,
location: PropTypes.shape({
pathname: PropTypes.string.isRequired,
}).isRequired,
diff --git a/client/components/pages/SettingsPage/SettingsPageContainer.js b/client/components/pages/SettingsPage/SettingsPageContainer.js
deleted file mode 100644
index 3130eb6..0000000
--- a/client/components/pages/SettingsPage/SettingsPageContainer.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-import SettingsPage from './SettingsPage';
-
-export default class SettingsPageContainer extends Component {
- static propTypes = {
- user: PropTypes.shape({}).isRequired,
- pushToLogin: PropTypes.func.isRequired,
- location: PropTypes.shape({
- pathname: PropTypes.string.isRequired,
- }).isRequired,
- }
-
- componentDidMount() {
- const { user, pushToLogin } = this.props;
- if (R.isEmpty(user)) {
- pushToLogin();
- }
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/pages/SettingsPage/index.js b/client/components/pages/SettingsPage/index.js
index ef71005..28d8bb9 100644
--- a/client/components/pages/SettingsPage/index.js
+++ b/client/components/pages/SettingsPage/index.js
@@ -1,7 +1,7 @@
import R from '_utils/ramda';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
-import SettingsPageContainer from './SettingsPageContainer';
+import SettingsPage from './SettingsPage';
const mapStateToProps = R.pick(['user']);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
pushToLogin: () => dispatch(push('/login')),
});
-export default connect(mapStateToProps, mapDispatchToProps)(SettingsPageContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(SettingsPage);
diff --git a/client/components/pages/TodoPage/TodoPage.js b/client/components/pages/TodoPage/TodoPage.js
index ef8601d..d094f8c 100644
--- a/client/components/pages/TodoPage/TodoPage.js
+++ b/client/components/pages/TodoPage/TodoPage.js
@@ -1,10 +1,29 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+import R from '_utils/ramda';
import TodoSection from '_templates/TodoSection';
-export default function TodoPage() {
- return (
+export default function TodoPage({ user, pushToLogin, getTodos }) {
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if (R.isEmpty(user)) {
+ pushToLogin();
+ } else {
+ getTodos()
+ .then(() => setLoading(false));
+ }
+ }, []);
+
+ return !loading && (
);
}
+
+TodoPage.propTypes = {
+ user: PropTypes.shape({}).isRequired,
+ pushToLogin: PropTypes.func.isRequired,
+ getTodos: PropTypes.func.isRequired,
+};
diff --git a/client/components/pages/TodoPage/TodoPageContainer.js b/client/components/pages/TodoPage/TodoPageContainer.js
deleted file mode 100644
index a575332..0000000
--- a/client/components/pages/TodoPage/TodoPageContainer.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-import TodoPage from './TodoPage';
-
-export default class TodoPageContainer extends Component {
- static propTypes = {
- user: PropTypes.shape({}).isRequired,
- pushToLogin: PropTypes.func.isRequired,
- getTodos: PropTypes.func.isRequired,
- }
-
- state = {
- loading: true,
- }
-
- componentDidMount() {
- const { user, pushToLogin, getTodos } = this.props;
- if (R.isEmpty(user)) {
- pushToLogin();
- } else {
- getTodos()
- .then(() => this.setState({ loading: false }));
- }
- }
-
- render() {
- return !this.state.loading && (
-
- );
- }
-}
diff --git a/client/components/pages/TodoPage/index.js b/client/components/pages/TodoPage/index.js
index 0e87cab..3761207 100644
--- a/client/components/pages/TodoPage/index.js
+++ b/client/components/pages/TodoPage/index.js
@@ -2,7 +2,7 @@ import R from '_utils/ramda';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
import { attemptGetTodos } from '_thunks/todos';
-import TodoPageContainer from './TodoPageContainer';
+import TodoPage from './TodoPage';
const mapStateToProps = R.pick(['user']);
@@ -11,4 +11,4 @@ const mapDispatchToProps = dispatch => ({
getTodos: () => dispatch(attemptGetTodos()),
});
-export default connect(mapStateToProps, mapDispatchToProps)(TodoPageContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(TodoPage);
diff --git a/client/components/pages/WelcomePage/WelcomePage.js b/client/components/pages/WelcomePage/WelcomePage.js
index 22a6296..d86b366 100644
--- a/client/components/pages/WelcomePage/WelcomePage.js
+++ b/client/components/pages/WelcomePage/WelcomePage.js
@@ -1,6 +1,14 @@
-import React from 'react';
+import React, { useEffect } from 'react';
+import PropTypes from 'prop-types';
+import R from '_utils/ramda';
+
+export default function WelcomePage({ user, pushToHome }) {
+ useEffect(() => {
+ if (!R.isEmpty(user)) {
+ pushToHome();
+ }
+ }, []);
-export default function WelcomePage() {
return (
@@ -13,3 +21,8 @@ export default function WelcomePage() {
);
}
+
+WelcomePage.propTypes = {
+ user: PropTypes.shape({}).isRequired,
+ pushToHome: PropTypes.func.isRequired,
+};
diff --git a/client/components/pages/WelcomePage/WelcomePageContainer.js b/client/components/pages/WelcomePage/WelcomePageContainer.js
deleted file mode 100644
index 4dfe98f..0000000
--- a/client/components/pages/WelcomePage/WelcomePageContainer.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import R from '_utils/ramda';
-import WelcomePage from './WelcomePage';
-
-export default class WelcomePageContainer extends Component {
- static propTypes = {
- user: PropTypes.shape({}).isRequired,
- pushToHome: PropTypes.func.isRequired,
- }
-
- componentDidMount() {
- const { user, pushToHome } = this.props;
- if (!R.isEmpty(user)) {
- pushToHome();
- }
- }
-
- render() {
- return (
-
- );
- }
-}
diff --git a/client/components/pages/WelcomePage/index.js b/client/components/pages/WelcomePage/index.js
index 451c07f..519a280 100644
--- a/client/components/pages/WelcomePage/index.js
+++ b/client/components/pages/WelcomePage/index.js
@@ -1,7 +1,7 @@
import R from '_utils/ramda';
import { connect } from 'react-redux';
import { push } from 'connected-react-router';
-import WelcomePageContainer from './WelcomePageContainer';
+import WelcomePage from './WelcomePage';
const mapStateToProps = R.pick(['user']);
@@ -9,4 +9,4 @@ const mapDispatchToProps = dispatch => ({
pushToHome: () => dispatch(push('/home')),
});
-export default connect(mapStateToProps, mapDispatchToProps)(WelcomePageContainer);
+export default connect(mapStateToProps, mapDispatchToProps)(WelcomePage);
diff --git a/client/hooks/useKeypress.js b/client/hooks/useKeypress.js
new file mode 100644
index 0000000..97ad493
--- /dev/null
+++ b/client/hooks/useKeypress.js
@@ -0,0 +1,21 @@
+import { useEffect } from 'react';
+
+export default function useKeypress(key, callback, active = true) {
+ useEffect(() => {
+ const keypress = e => {
+ if (e.key === key) {
+ callback();
+ }
+ };
+
+ if (active) {
+ window.addEventListener('keypress', keypress);
+ }
+
+ return () => {
+ if (active) {
+ window.removeEventListener('keypress', keypress);
+ }
+ };
+ }, [callback, active]);
+}
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 022b767..a7f1de7 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -75,6 +75,7 @@ module.exports = {
_assets: resolve('client/assets/'),
_styles: resolve('client/styles/'),
_utils: resolve('client/utils/'),
+ _hooks: resolve('client/hooks/'),
_api: resolve('client/api/'),
},
},
diff --git a/package.json b/package.json
index 77b6613..b6da1b1 100644
--- a/package.json
+++ b/package.json
@@ -72,6 +72,7 @@
"^_assets(.*)$": "
/client/assets/$1",
"^_styles(.*)$": "/client/styles/$1",
"^_utils(.*)$": "/client/utils/$1",
+ "^_hooks(.*)$": "/client/hooks/$1",
"^_api(.*)$": "/client/api/$1"
},
"setupFiles": [