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