https://codeburst.io/getting-started-with-react-router-5c978f70df91
React components
npx create-react-app <app> --typescript npm start
React-Bootstrap
https://react-bootstrap.github.io/getting-started/why-react-bootstrap/
# install yarn npm i -g yarn yarn add @blueprintjs/core @blueprintjs/icons @blueprintjs/datetime @blueprintjs/select @blueprintjs/timezone
Things to learn:
- PureComponent => class MessageBox extends PureComponent
- ForceUpdate (Component) => this.forceUpdate() // iso this.setState({ … })
- Properties to child: <Child {…this.props} />
componentDidUpdate (prevProps, prevState, snapshot) // Use setState() here, but remember to compare props shouldComponentUpdate (newProps, newState) // Skips render() if returns false render() // Render componentDidUpdate (prevProps, prevState) // Operate on the DOM here //Dom reference class MyComponent extends Component { render () { return <div> <input ref={el => this.input = el} /> </div> } componentDidMount () { this.input.focus() } } // Lists class TodoList extends Component { render () { const { items } = this.props return <ul> {items.map(item => <TodoItem item={item} key={item.key} />)} </ul> } } <div onMouseEnter={() => setText("You hovered over me!")} onMouseLeave={() => setText("Hover over me to see changes")} > function HelloWorld (props){ const [text, setText] = useState(props.text) return ( <div>{text}</div> ) } render() { const [isLoading, setIsLoading] = useState(false); return ( <div className="App"> {isLoading ? <div>Loading...</div> : <div>Done!</div>} </div> ); }
interface SquareProps { value: string onClick: (event: any) => void; } export function Square(props: SquareProps) { return ( <button className="square" onClick={props.onClick}> {props.value} </button> ); }
import React from "react"; import { Square } from "./Square"; interface BoardProps { squares: string[]; onClick: (event: any) => void; } interface BoardState { squares: string[]; xIsNext: boolean; } export class Board extends React.Component<BoardProps, BoardState> { renderSquare(i: number) { return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />; } render() { return ( <div> <div className="board-row"> {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} </div> <div className="board-row"> {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} </div> <div className="board-row"> {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} </div> </div> ); } }
import React from "react"; import { Board } from "./Board"; interface GameState { history: any[]; xIsNext: boolean; stepNumber: number; } export class Game extends React.Component<{}, GameState> { constructor(props: {}) { super(props); this.state = { history: [{ squares: Array(9).fill(null), }], stepNumber: 0, xIsNext: true }; } handleClick(i: number) { const history = this.state.history.slice(0, this.state.stepNumber + 1); const current = history[history.length - 1]; const squares = current.squares.slice(); if (calculateWinner(squares) || squares[i]) { return; } squares[i] = this.state.xIsNext ? 'X' : 'O'; this.setState({ history: history.concat([{ squares: squares, }]), stepNumber: history.length, xIsNext: !this.state.xIsNext }); } jumpTo(step: number) { this.setState({ stepNumber: step, xIsNext: (step % 2) === 0, }); } render() { const history = this.state.history; const current = history[this.state.stepNumber]; const winner = calculateWinner(current.squares); const moves = history.map((step, move) => { const desc = move ? 'Go to move #' + move : 'Go to game start'; return ( <li key={move}> <button onClick={() => this.jumpTo(move)}>{desc}</button> </li> ); }); let status; if (winner) { status = 'Winner: ' + winner; } else { status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O'); } return ( <div className="game"> <div className="game-board"> <Board squares={current.squares} onClick={(i) => this.handleClick(i)} /> </div> <div className="game-info"> <div>{status}</div> <ol>{moves}</ol> </div> </div> ); } } function calculateWinner(squares: string[]) { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6], ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { return squares[a]; } } return null; }
import React from "react"; interface LoginProps {} interface LoginState { username: string; password: string; } export class Login extends React.Component<LoginProps, LoginState> { constructor(props: LoginProps) { super(props); this.state = { username: "", password: "" }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event: React.ChangeEvent<HTMLInputElement>) { const target = event.target; (this.state as any)[target.name] = target.value; this.setState(this.state); } handleSubmit(event: React.FormEvent<HTMLFormElement>) { console.log('Form was submitted: ', this.state); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> User name: <input name="username" type="text" value={this.state.username} onChange={this.handleChange} /> </label> <br /> <label> Password: <input name="password" type="password" value={this.state.password} onChange={this.handleChange} /> </label> <button type="submit">Login</button> </form> ); } }
import React from 'react'; import logo from './logo.svg'; import './App.css'; import { Router, Route, RouteComponentProps } from 'react-router'; import { Link, HashRouter } from 'react-router-dom'; function App() { return ( <HashRouter> <div> <Header /> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/topics" component={Topics} /> </div> </HashRouter> ); } function Home() { return <h2>Home</h2>; } function About() { return <h2>About</h2>; } function Topic({ match }: RouteComponentProps<{ id: string }>) { return <h3>Requested Param: {match.params.id}</h3>; } function Topics({ match }: RouteComponentProps<{}>) { return ( <div> <h2>Topics</h2> <ul> <li> <Link to={`${match.url}/components`}>Components</Link> </li> <li> <Link to={`${match.url}/props-v-state`}>Props v. State</Link> </li> </ul> <Route path={`${match.path}/:id`} component={Topic} /> <Route exact path={match.path} render={() => <h3>Please select a topic.</h3>} /> </div> ); } function Header() { return ( <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> li> <li> <Link to="/topics">Topics</Link> </li> </ul> ); } export default App;
import React from "react"; interface TextInputProps { label: string; name: string; value?: string; isPassword?: boolean; onChange: (value: string) => void } interface TextInputState { value: string; type: string; } export class TextInput extends React.Component<TextInputProps, TextInputState> { constructor(props: TextInputProps) { super(props); this.state = { value: this.props.value || "", type: this.props.isPassword ? "password" : "text" }; this.handleChange = this.handleChange.bind(this); } handleChange(event: React.ChangeEvent<HTMLInputElement>) { const value = event.target.value; if (value !== this.state.value) { this.setState({ value }); this.props.onChange(value); } } render() { return ( <label> {this.props.label} <input name={this.props.name} type={this.state.type} value={this.state.value} onChange={this.handleChange} /> </label> ); } }
const Wrapper = ({children}) => ( <div> <div>header</div> <div>{children}</div> <div>footer</div> </div> ); const App = () => <div>Hello</div>; const WrappedApp = () => ( <Wrapper> <App/> </Wrapper> );
import React from 'react'; import './App.css'; import { Wiring } from './wiring/Wiring'; import { Route, Switch, Redirect } from 'react-router'; import { HashRouter } from 'react-router-dom'; import { LoginView } from './view/LoginView'; import { MonthView } from './view/MonthView'; import { DayView } from './view/DayView'; import { NavMenu } from './components/NavMenu'; import { RedirectToToday, RedirectToLogin } from './view/Redirects'; import { appDomain } from './domain/AppDomain'; new Wiring(); function LoginRoutes() { return ( <HashRouter> <Switch> <Route exact path="/login" component={LoginView} /> <Route path="*" component={RedirectToLogin} /> </Switch> </HashRouter> ); } function PrivateRoutes() { return ( <HashRouter> <NavMenu /> <Switch> <Route exact path="/" component={RedirectToToday} /> <Route path="/day" component={DayView} /> <Route path="/month" component={MonthView} /> <Route component={RedirectToToday} /> </Switch> </HashRouter> ); } export class App extends React.Component { render() { //const hasPermission = appDomain.IRequestPermission.hasPermission(null); const hasPermission = false; if (hasPermission) { return (<PrivateRoutes />) } return (<LoginRoutes />) } } export default App;
import React from "react"; import { dateAdd } from "../helpers/tsHelpers"; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; const day = 1000 * 60 * 60 * 24; interface DateNavigatorProps { value?: Date | null; onChange: (value: Date | null) => void } interface DateNavigatorState { value?: Date | null; } export class DateNavigator extends React.Component<DateNavigatorProps, DateNavigatorState> { constructor(props: DateNavigatorProps) { super(props); this.state = { value: this.props.value }; } prevDate() { this.handleChange(dateAdd(this.state.value, -day)); } nextDate() { this.handleChange(dateAdd(this.state.value, day)); } handleChange(value: Date | null) { if (value !== this.state.value) { this.setState({ value }); this.props.onChange(value); } } static getDerivedStateFromProps(nextProps: DateNavigatorProps, prevState: DateNavigatorState): Partial<DateNavigatorState> | null { if (prevState.value !== nextProps.value) { return { value: nextProps.value }; } return null; } render() { return ( <div className="date-navigator"> <div className="button-prev" onClick={this.prevDate.bind(this)}><</div> <div className="date-picker"> <DatePicker todayButton={"Vandaag"} locale="nl-NL" selected={this.state.value} onChange={this.handleChange.bind(this)} dateFormat="iiii d MMMM yyyy" /> </div> <div className="button-next" onClick={this.nextDate.bind(this)}>></div> </div> ); } }
import React from 'react'; import { appDomain } from './domain/AppDomain'; import { PrivateRoutes } from './routes/PrivateRoutes'; import { PublicRoutes } from './routes/PublicRoutes'; import { RouteComponentProps, withRouter } from 'react-router'; import { INavigateTo } from './domain/ports/secondary/INavigateTo'; import { NavigationPlug } from './adapters/NavigationAdapter/NavigationPlug'; import { wiring } from './App'; export class RoutingWrapperBase extends React.Component<RouteComponentProps> { unlisten: Function | null = null; componentDidMount() { this.handleLocationChange(this.props.history.location); this.unlisten = this.props.history.listen(this.handleLocationChange); } componentWillUnmount() { if (this.unlisten) { this.unlisten(); } } handleLocationChange(location: any) { // your staff here console.log(`location`, location); } render() { const navigateFn = (path: string, state?: any) => this.props.history.push(path, state); wiring.portResolver.registerInstance<INavigateTo>("INavigateTo", () => new NavigationPlug(navigateFn)); const hasPermission = appDomain.IRequestPermission.hasPermission(null); if (hasPermission) { return (<PrivateRoutes />); } return (<PublicRoutes />); } } export const RoutingWrapper = withRouter(RoutingWrapperBase);
import React from "react"; import { IEventSubscription } from "../../domain/ports/primary/IEventHandler"; import { appDomain } from "../../domain/AppDomain"; export class BaseComponent<P = {}, S = {}, SS = any> extends React.Component<P, S, SS> { private _unmounted = false; private _subscriptions: IEventSubscription[]; constructor(props: P) { super(props); this._subscriptions = []; } mounted() { return !this._unmounted; } componentDidMount() { // add mount code } componentWillUnmount() { this._unmounted = true; this._subscriptions.forEach(s => s.unsubscribe()); } addEventListener(element: EventTarget, event: string, handler: EventListenerOrEventListenerObject) { element.addEventListener(event, handler); this._subscriptions.push({ unsubscribe: () => element.removeEventListener(event, handler) }); } subscribe(event: string, fn: (data: any) => void) { return appDomain.IEventHandler.subscribe(event, fn); } subscribeInterval(fn: Function, ms: number): void { const interval = setInterval(fn, ms); this._subscriptions.push({ unsubscribe: () => clearInterval(interval) }); } translate(key: string, params?: any): string { return appDomain.IRequestTranslation.translate(key, params); } navigateTo(url: string, params: any = {}): void { appDomain.INavigator.navigateTo(url, params); } }
249100cookie-checkReact