Listings Springer/react_lib

Listing 1: Definition von Routen
import { BrowserRouter as Router, Route } from 'react-router-dom';

export default function App() {
    return (
      <Router>
        <Route exact={true} path="/" component={Start} />
        <Route path="/quiz" component={Quiz} />
      </Router>
    );
}

-------

Listing 2: Fehlerbehandlung mit der Switch-Komponente
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

export default function App() {
    return (
      <Router>
        <Switch>
          <Route exact={true} path="/" component={Start} />
          <Route path="/quiz" component={Quiz} />
          <Route path="/" component={NotFound} />
        </Switch>
      </Router>
    );
}

-------

Listing 3: Verwendung der withRouter HOC
import { RouteComponentProps } from 'react-router';

interface Props {...}

export default function Quiz({

    match,
}: Props & RouteComponentProps<{ id: string }>) {
    useEffect(() => {
      getQuestion(match.params.id);
    }, [getQuestion, match.params.id]);

    ...

    return (
      <>
        {question && (
          <div className={classNames.join(' ')}>
            ...
          </div>
        )}
      </>
    );
}

-------

Listing 4: Navigation aus Redux heraus
import { push } from 'connected-react-router';

...

const finishEpic = (action$: Observable<ActionType<typeof finishAction>>) =>
    action$.pipe(
      ofType(FINISH),
      mergeMap(action => of(push('/summary')))
    );

  ...

export default combineEpics(
    getQuestionEpic, 
    answerQuestionEpic, 
    finishEpic,
);

-------

Listing 5: Eingaben mit Material-UI
import TextField from '@material-ui/core/TextField';

export default function Start() {
    const [name, setName] = useState('');

    ...

    return (
      <div>
        ...
        <TextField
          id="userName"
          label="Name"
          value={name}
          onChange={e => setName(e.currentTarget.value)}
          margin="normal"
        />
        ...
      </div>
    );
}

-------

Listing 6: Dialog-Komponente für die Beispielapplikation
import React from 'react';
import {
    Dialog,
    DialogTitle,
    DialogContent,
    DialogActions,
    Button,
} from '@material-ui/core';
import Summary from '../quiz/Summary.container.component';

interface Props {
    open: boolean;
    onClose: () => {};
}

export default function Finish({ open, onClose }: Props) {
    return (
      <Dialog open={open} onClose={onClose}>
        <DialogTitle>Herzlichen Glückwunsch, Sie haben es geschafft!</DialogTitle>
        <DialogContent>
          <Summary />
        </DialogContent>
        <DialogActions>
          <Button onClick={onClose}>weiter</Button>
        </DialogActions>
      </Dialog>
    );
}

-------

Listing 7: Die Highscore-Komponente mit der Material-UI-Tabelle
interface Props {
    highscores: Array<{
      name: string;
      questions: number;
      correct: number;
      wrong: number;
    }>;
}

type columns = 'name' | 'questions' | 'correct' | 'wrong';

export default function List({ highscores }: Props) {
    const [filter, setFilter] = useState('');
    const [sort, setSort] = useState<{
      orderBy: columns;
      order: 'asc' | 'desc';
    }>({
      orderBy: 'name',
      order: 'asc',
    });

    const createSortHandler = (columnId: columns) => {
      return () => {
        setSort({
          orderBy: columnId,
          order: sort.order === 'asc' ? 'desc' : 'asc',
        });
      };
    };

    return (
      <Paper>
        <TextField
          label="Liste filtern"
          value={filter}
          onChange={(e: ChangeEvent<HTMLInputElement>) =>
            setFilter(e.currentTarget.value)
          }
        />
        <Table>
          <TableHead>
            <TableRow>
              <TableCell>
                <TableSortLabel
                  active={sort.orderBy === 'name'}
                  direction={sort.order}
                  onClick={createSortHandler('name')}
                >
                  Name
                </TableSortLabel>
              </TableCell>
              ...
            </TableRow>
          </TableHead>
        <TableBody>
            {highscores
              .filter(highscore =>
                highscore.name.toLowerCase().includes(filter.toLowerCase())
              )
              .sort((scoreA, scoreB) => {
                let result = 0;
                if (scoreB[sort.orderBy]! < scoreA[sort.orderBy]!) {
                  result = -1;
                }
                if (scoreB[sort.orderBy]! > scoreA[sort.orderBy]!) {
                  result = 1;
                }
                return sort.order === 'asc' ? result * -1 : result;
              })
              .map((highscore, index) => (
                <TableRow key={index}>
                  <TableCell>{highscore.name}</TableCell>
                  ...
                </TableRow>
              ))}
          </TableBody>
        </Table>
      </Paper>
    );
}
