Walkthrough and React Fundamentals:
Initialize app
In src/index.jsx
comment out lines 17-34, and replace with:ReactDOM.render(<div>Hello World</div>, document.getElementById('root')
Fetch data from a variety of devstack apis
Display data in generic JSX
Generate custom display of devstack API data with Paragon components
Send messages to devstack API and update on response
Topics to review:
How does a react app “initialize”? What is different about MFE initialization? Why?
Brief understanding of tools:
Webpack
Babel
Eslint
Jest
Helpful simple ES6 syntax
React components
What makes a component?
How to define PropTypes?
What makes a component update (component lifecycle)?
Behavior vs render
Basic hooks for render (useState, useEffect)
Generic custom hook extraction
How to test generic react behavior
Network interaction
What are Promises? How do they work? How do we work with them?
How do we make asynchronous network requests?
Where should network requests be defined in the project?
How do we load data in from network api sources?
Example Output
import React from 'react'; import { useKeyedState } from '@edx/react-unit-test-utils'; import { Container } from '@edx/paragon'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { getConfig } from '@edx/frontend-platform/config'; const apis = { courses: 'courses/v1/courses/', mfe_context: 'mfe_context', }; const { courses } = apis; const courseAPIs = { // blocks: (course_id) => `courses/v2/blocks/?course_id=${course_id}`, instructorReports: (course_id) => `instructor/v1/reports/${course_id}`, instructorTaskScheduledBulkEmails: (course_id) => `instructor_task/v1/schedules/${course_id}/bulk_email/`, }; const ExamplePage = () => { const get = (uri) => getAuthenticatedHttpClient() .get(`${getConfig().LMS_BASE_URL}/api/${uri}`); const [apiObjects, setAPIObjects] = useKeyedState('apiObjects', {}); const [courseAPIObjects, setCourseAPIObjects] = useKeyedState('courseAPIObjects', {}); const logAPI = (key, uri) => { get(uri).then(({ data }) => { apiObjects[key] = data; }); }; React.useEffect(() => { Object.keys(apis).forEach(key => { get(apis[key]).then(({ data }) => { setAPIObjects({ ...apiObjects, [key]: data }); setAPIObjects((old) => ({ ...old, [key]: data })); }); }); get('courses/v1/courses/').then(({ data }) => { const { course_id } = data.results[0]; Object.keys(courseAPIs).forEach(key => { get(courseAPIs[key](course_id)).then(({ data }) => { setCourseAPIObjects((old) => ({ ...old, [key]: data })); }); }); }); }, []); return ( <main> <Container className="py-5"> <h1>Example Page</h1> <p>Hello world!</p> <br /> <b>API Objects</b> {Object.keys(apiObjects).map((key) => ( <pre>{JSON.stringify(apiObjects[key], null, 2)}</pre> ))} <br /> <b>Course API Objects</b> {Object.keys(apiObjects).map((key) => ( <pre>{JSON.stringify(apiObjects[key], null, 2)}</pre> ))} </Container> </main> ); }; export default ExamplePage;