From cb8ac3cf63a4c9e8d5ab699642f25a7764ca2b6d Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Sat, 18 Jan 2020 01:27:56 +0000 Subject: [PATCH] Force refresh of states instead of modifying objects --- webclient/src/Account.js | 10 ++++++---- webclient/src/Admin.js | 29 ++++++++++++++++------------- webclient/src/App.js | 11 ++++++----- webclient/src/Classes.js | 27 ++++++++++----------------- webclient/src/Members.js | 11 ++++++----- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/webclient/src/Account.js b/webclient/src/Account.js index d0c95fe..1dab643 100644 --- a/webclient/src/Account.js +++ b/webclient/src/Account.js @@ -6,6 +6,7 @@ import { BasicTable, staticUrl, requester } from './utils.js'; import { LoginForm, SignupForm } from './LoginSignup.js'; function ChangePasswordForm(props) { + const { token } = props; const [input, setInput] = useState({}); const [error, setError] = useState({}); const [loading, setLoading] = useState(false); @@ -17,7 +18,7 @@ function ChangePasswordForm(props) { const handleSubmit = (e) => { setLoading(true); - requester('/password/change/', 'POST', props.token, input) + requester('/password/change/', 'POST', token, input) .then(res => { setError({}); history.push('/'); @@ -67,7 +68,8 @@ function ChangePasswordForm(props) { }; export function AccountForm(props) { - const member = props.user.member; + const { token, user, refreshUser } = props; + const member = user.member; const [input, setInput] = useState({ ...member, set_details: true }); const [error, setError] = useState({}); const [loading, setLoading] = useState(false); @@ -80,10 +82,10 @@ export function AccountForm(props) { const handleSubmit = (e) => { setLoading(true); - requester('/members/' + member.id + '/', 'PATCH', props.token, input) + requester('/members/' + member.id + '/', 'PATCH', token, input) .then(res => { setError({}); - props.setUserCache({...props.user, member: res}); + refreshUser(); history.push('/'); }) .catch(err => { diff --git a/webclient/src/Admin.js b/webclient/src/Admin.js index a31da82..6bd5b25 100644 --- a/webclient/src/Admin.js +++ b/webclient/src/Admin.js @@ -5,11 +5,12 @@ import { Container, Checkbox, Divider, Dropdown, Form, Grid, Header, Icon, Image import { BasicTable, staticUrl, requester } from './utils.js'; function AdminCardDetail(props) { - const [input, setInput] = useState({ ...props.card }); + const { token, result, card } = props; + const [input, setInput] = useState({ ...card }); const [error, setError] = useState(false); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); - const id = props.card.id; + const id = card.id; const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value }); const handleUpload = (e, v) => setInput({ ...input, [v.name]: e.target.files[0] }); @@ -19,8 +20,8 @@ function AdminCardDetail(props) { const handleSubmit = (e) => { setLoading(true); setSuccess(false); - const data = { ...input, member_id: props.result.member.id }; - requester('/cards/'+id+'/', 'PUT', props.token, data) + const data = { ...input, member_id: result.member.id }; + requester('/cards/'+id+'/', 'PUT', token, data) .then(res => { setLoading(false); setSuccess(true); @@ -37,7 +38,7 @@ function AdminCardDetail(props) { const handleDelete = (e) => { e.preventDefault(); - requester('/cards/'+id+'/', 'DELETE', props.token) + requester('/cards/'+id+'/', 'DELETE', token) .then(res => { setInput(false); }) @@ -98,13 +99,14 @@ function AdminCardDetail(props) { : - Deleted card: {props.card.card_number} + Deleted card: {card.card_number} ); }; export function AdminMemberCards(props) { - const cards = props.result.cards; + const { token, result, refreshResult } = props; + const cards = result.cards; const [input, setInput] = useState({ active_status: 'card_active' }); const [error, setError] = useState(false); const [loading, setLoading] = useState(false); @@ -119,13 +121,13 @@ export function AdminMemberCards(props) { const handleSubmit = (e) => { setLoading(true); setSuccess(false); - const data = { ...input, member_id: props.result.member.id }; - requester('/cards/', 'POST', props.token, data) + const data = { ...input, member_id: result.member.id }; + requester('/cards/', 'POST', token, data) .then(res => { setLoading(false); setSuccess(true); setError(false); - props.setResult({ ...props.result, cards: [...cards, res] }); + refreshResult(); }) .catch(err => { setLoading(false); @@ -194,7 +196,8 @@ export function AdminMemberCards(props) { }; export function AdminMemberForm(props) { - const [input, setInput] = useState(props.result.member); + const { token, result, refreshResult } = props; + const [input, setInput] = useState(result.member); const [error, setError] = useState(false); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); @@ -208,12 +211,12 @@ export function AdminMemberForm(props) { const handleSubmit = (e) => { setLoading(true); setSuccess(false); - requester('/members/' + id + '/', 'PATCH', props.token, input) + requester('/members/' + id + '/', 'PATCH', token, input) .then(res => { setLoading(false); setSuccess(true); setError(false); - props.setResult({ ...props.result, member: res }); + refreshResult(); }) .catch(err => { setLoading(false); diff --git a/webclient/src/App.js b/webclient/src/App.js index e5c6231..7303f64 100644 --- a/webclient/src/App.js +++ b/webclient/src/App.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useReducer } from 'react'; import { BrowserRouter as Router, Switch, Route, Link, useParams } from 'react-router-dom'; import './light.css'; import { Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react'; import { requester } from './utils.js'; @@ -16,6 +16,7 @@ import { Footer } from './Footer.js'; function App() { const [token, setToken] = useState(localStorage.getItem('token', '')); const [user, setUser] = useState(JSON.parse(localStorage.getItem('user', 'false'))); + const [refreshCount, refreshUser] = useReducer(x => x + 1, 0); function setTokenCache(x) { setToken(x); @@ -36,7 +37,7 @@ function App() { console.log(err); setUser(false); }); - }, [token]); + }, [token, refreshCount]); function logout() { setTokenCache(''); @@ -121,14 +122,14 @@ function App() { - +
{user && user.member.set_details ? - + @@ -154,7 +155,7 @@ function App() { - + diff --git a/webclient/src/Classes.js b/webclient/src/Classes.js index 1bae213..3cdf445 100644 --- a/webclient/src/Classes.js +++ b/webclient/src/Classes.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useReducer } from 'react'; import { BrowserRouter as Router, Switch, Route, Link, useParams } from 'react-router-dom'; import './light.css'; import { Button, Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react'; @@ -66,7 +66,8 @@ export function Classes(props) { return (
Class List
-
Upcoming
+ +
Upcoming
{classes ? x.datetime > now)} /> : @@ -85,8 +86,9 @@ export function Classes(props) { export function ClassDetail(props) { const [clazz, setClass] = useState(false); + const [refreshCount, refreshClass] = useReducer(x => x + 1, 0); const [error, setError] = useState(false); - const { token, user, setUserCache } = props; + const { token, user, refreshUser } = props; const { id } = useParams(); const userTraining = user.training.find(x => x.session.id == id); @@ -99,20 +101,17 @@ export function ClassDetail(props) { console.log(err); setError(true); }); - }, []); + }, [refreshCount]); const handleSignup = () => { const data = { attendance_status: 'waiting for payment', session: id }; requester('/training/', 'POST', token, data) .then(res => { - // bad code: - const newClass = { ...clazz, student_count: clazz.student_count+1 }; - setUserCache({ ...user, training: [...user.training, {...res, session: newClass }] }); - setClass(newClass); + refreshClass(); + refreshUser(); }) .catch(err => { console.log(err); - setError(true); }); }; @@ -120,14 +119,8 @@ export function ClassDetail(props) { const data = { attendance_status: newStatus, session: id }; requester('/training/'+userTraining.id+'/', 'PUT', token, data) .then(res => { - // bad code: - const studentChange = newStatus === 'withdrawn' ? -1 : 1 - const newClass = { ...clazz, student_count: clazz.student_count + studentChange }; - const trainingIndex = user.training.indexOf(userTraining); - const newTraining = user.training; - newTraining[trainingIndex] = {...res, session: newClass }; - setUserCache({ ...user, training: newTraining }); - setClass(newClass); + refreshClass(); + refreshUser(); }) .catch(err => { console.log(err); diff --git a/webclient/src/Members.js b/webclient/src/Members.js index 571e574..d016359 100644 --- a/webclient/src/Members.js +++ b/webclient/src/Members.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useReducer } from 'react'; import { BrowserRouter as Router, Switch, Route, Link, useParams } from 'react-router-dom'; import './light.css'; import { Button, Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Input, Item, Menu, Message, Segment, Table } from 'semantic-ui-react'; @@ -74,6 +74,7 @@ export function Members(props) { export function MemberDetail(props) { const [result, setResult] = useState(false); + const [refreshCount, refreshResult] = useReducer(x => x + 1, 0); const [error, setError] = useState(false); const { token, user } = props; const { id } = useParams(); @@ -87,7 +88,7 @@ export function MemberDetail(props) { console.log(err); setError(true); }); - }, []); + }, [refreshCount]); const member = result.member || false; @@ -105,7 +106,7 @@ export function MemberDetail(props) {

{isAdmin(user) ? - + : @@ -124,13 +125,13 @@ export function MemberDetail(props) { {isAdmin(user) && - + } {isAdmin(user) && - + }