jsconfig.json
file in the root folder
{ "compilerOptions": { "baseUrl": "src" }, "include": ["src"] }
Put App.js
under components
folder
Import as
import App from 'components/App';
package.json
"homepage": "/projects/211/projName/",
index.html
<base href="%PUBLIC_URL%/">
App.js
import { BrowserRouter as Router } from 'react-router-dom';
function App() { return ( <Router basename={process.env.PUBLIC_URL}> {/* Basename is used due to deployment in subfolder on my web site */} ... </Router> ); }
??
null conditional operator
const initialValues = selectedEvent ?? { title: "", date: "", };
userResources.filter(({ id, uniqueId }) => id !== payload.resourceId && uniqueId !== payload.uniqueId)
const onSubmit = () => { selectedEvent ? updateEvent({ ...selectedEvent, ...values }) // override previous values : createEvent({ ...values, id: cuid(), hostedBy: "Bob", attendees: [], hostPhotoURL: "./assets/user.png", }); };
<Router> <Route exact path='/' component={Homepage} /> {/* don't show NavBar here */} <Route path={"/(.+)"} // path other than '/' render={() => ( <> <NavBar setFormOpen={onFormOpen} selectEvent={handleSelectEvent} /> <Container className='main'> <Route exact path='/events' component={EventDashboard} /> <Route path='/events/:id' component={EventDetailedPage} /> </Container> </> )} /> </Router>See Re-events project #267, #268, #269
import {useHistory} from 'react-router-dom'; const history = useHistory(); const onSubmit = () => { ... history.push("/account"); };
const LoginForm = () => { const mode = new URLSearchParams(window.location.search).get("mode"); const actionCode = new URLSearchParams(window.location.search).get("oobCode"); } https://mySite.app/login?mode=action&oobCode=code
useEffect()
useEffect()
runs after every component render:
useEffect(() => { document.title = `You clicked ${count} times`; });
useEffect()
runs only if count
was changed
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]);
useEffect()
- run only on initial render
useEffect(() => { ... // eslint-disable-next-line }, []);
useEffect()
with cleanup
useEffect(() => { ... // Cleanup code return () => { window.removeEventListener('mousemove', logMousePosition); } }, []);
const [count, setCount] = useState(0) const tick = () => { setCount(count + 1) } useEffect(() => { const interval = setInterval(tick, 1000) return () => { clearInterval(interval) } }, [count])
Same as
const [count, setCount] = useState(0) const tick = () => { setCount(prevCount => prevCount + 1) } useEffect(() => { const interval = setInterval(tick, 1000) // Cleanup return () => { clearInterval(interval) } }, [])
UseEffect()
useEffect(() => { function doSomething() { console.log(someProp); } doSomething(); const interval = setInterval(tick, 1000) // Cleanup return () => { clearInterval(interval) } }, [someProp])
useEffect
useEffect(() => { async function fetchData() { const url = `https://api.github.com/users`; setLoading(true); const response = await axios.get(url) setUsers(response.data) setLoading(false); } fetchData(); }, []);
useEffect
import { useState, useEffect } from 'react'; import axios from 'axios'; import PostItem from './PostItem'; const PostList = () => { const [posts, setPosts] = useState({}); // Object.values(posts) is an array of post objects. !!!!! const fetchPosts = async () => { const rootUrl = process.env.REACT_APP_POSTS_BASE_URL; const res = await axios.get(`${rootUrl}/posts`); setPosts(res.data); }; useEffect(() => { fetchPosts(); }, []); return ( <div className="d-flex flex-row flex-wrap justify-content-between"> {Object.values(posts).map((post) => ( <PostItem key={post.id} post={post} /> ))} </div> ); }; export default PostList;
useEffect
calls in the same component
useEffect(() => { } useEffect(() => { }
import { useEffect } from "react"; import { useLocation } from "react-router-dom"; export default function ScrollToTop() { const { pathname } = useLocation(); useEffect(() => { window.scrollTo(0, 0); }, [pathname]); return null; }
<Router> <ScrollToTop /> </Router>See project #268 Re-vents
"scripts": { "build": "cross-env GENERATE_SOURCEMAP=false react-scripts build", }