AWS & Typescript Masterclass - 9. Front-end for our back-end with React

September 17th, 2022

62-81


(63) Create react app and git

npx create-react-app space-finder-frontend --template typescript

 


(64) Basic project structure

folder structure

  • components: ui components (*.tsx)

  • model: types (*.ts)

  • services: non-ui code (*.ts)

  • util (*.ts)

 


 

(65) state, props, child, parent

change in state or props triggers re-render

 

props are immutable

state is mutable

this.setState({

counterState: this.state.counterState + 1

})

 

 

use state / props

this.state.counterState

this.props.counterProp

 

typescript class defines type of Props and State

interface Props {

counterProp: number

}

interface State {

counterState: number

}

export class MyComponent extends React.Component<Props, State>{

state: State = {

counter: 0

}

}

 

pass data to child with props

interface AppState {

appCounter: number

}

export class App extends React.Component<{}, AppState>{

render() {

return (<MyComponent counterProp=={this.state.appCounter}>)

}

}

 


(67) Child components

function foo(): Promise<User | undefined>

?? why succeed with undefined instead of using promise.reject for that?

 


(68) Handling events

via properties

  • onChange    // every letter change (on input)

  • onSubmit     // submit button (on form)

interface CustomEvent {

target: HTMLInputElement

}

 

class Component ... {

private setUserName(event: CustomEvent){

this.setState({userName: event.target.value})

}

 

private async handleSubmit(event: SyntheticEvent) {

event.preventDefault();

const result = await this.props.authService.login(this.state.userName)

...

}

render() {

return (

<form onSubmit={e=>this.handleSubmit(e)}

<input value={this.state.userName} onChange={e=>this.setUserName(e)}>

</form>

)

}

}

 


(70) Data from child to parent

React: Passing Functions to Components

 


 

(71-72) Routing

npm i react-router-dom @types/react-router-dom

 

NavBar

import {Link} from 'react-router-dom'

 

<div className='navbar'>

<Link to='/'>Home</Link>

<Link to='/profile'>Home</Link>

 

Router

import {Router, Route, Switch} from 'react-router-dom'

import history from '../utils/history'

 

<div className='wrapper'>

<Router history={history}>

<div>

<Navbar user={this.state.user}/>

<Switch>

<Route exact path='/' component={Home}/>    // cannot pass properties

<Route exact path='/login'>    // to pass properties

<Login .../>

<Route exact path='/profile' component={Profile}/>

</Router>

 

utils/history.ts

import {createBrowserHistory} from 'history'

export default createBrowserHistory();

 


(73) Small Css

 

(a) Global CSS file + className property

add global css to index.tsx with an import

index.tsx

import ReactDOM from 'react-dom'

import {App} from './components/App'

import './index.css'    // <<<<<<

 

ReactDOM.render(<App/>, document.getElementById('root'))

 

(b) style property

<Link style={{float:'right'}} ...

 

> (c) others not mentioned in this course

 


(74) State of the application

aka. persisting navigation state

import history from '../utils/history'

 

history.push('/profile')


(75-76) Rendering async table

async componentDidMount() {

const userAttributes = await this.props.authService.getUserAttributes(this.props.user)

this.setState({userAttributes})

}


(77) Space component build

refer to image asset

import genericImage from '../../assets/geneirc-image.jpg'

 

<img src={genericImage} alt=''/>


(79) Routing and styling spaces

components/spaces/SpaceComponent.tsx

import './SpaceComponent.css'

components/spaces/SpaceComponent.css

...


(80) Modal content

aka in page popups

hide component

render() {return null}

-> when we return null, react will just not render it (confirmed: Conditional Rendering – React)

 

modal component

  • flag to toggle showing

  • external close method

  • css to make it appear like a popup

components/spaces/ConfirmModalComponent.tsx

import './ConfirmModalComponent.css'

 

interface ConfirmModalComponentProps {

show: boolean

close: () => void

}

 

export class ConfirmModalComponent extends Component<ConfirmModalComponentProps>{

render() {

if(!this.props.show) return null

return <div className='modal'>

<button onClick={this.props.close()}>OK</button>

</div>

}

}

components/spaces/ConfirmModalComponent.css

.modal {

z-index: 1;    // must be on top

position: fixed;

}