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;
}