LoginSignup
0
2

More than 5 years have passed since last update.

React JSX

Posted at

概要

TypeScript Deep DiveのReact JSXをやってみる。

https://typescript-jp.gitbook.io/deep-dive/tsx/react
https://basarat.gitbooks.io/typescript/docs/jsx/react.html

Function Components(関数コンポーネント)

React.FunctionComponentを使用して関数コンポーネントを定義する。
以降は、<script type="text/babel"></script>を変更していくことにする。

index.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />

    <title>Hello React!</title>

    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>

<body>
    <div id="root"></div>
</body>

</html>

<script type="text/babel">

    type Props = {
      foo: string;
    }

    const MyComponent: React.FunctionComponent<Props> = (props) => {
        return <span>{props.foo}</span>
    }

    ReactDOM.render(<MyComponent foo="bar" />, document.getElementById('root'));

</script>

Class Components(クラスコンポーネント)

Componentクラスを継承して独自クラスを作成する。

index.d.tsからComponentクラス抜粋
// Base component for plain JS classes
// tslint:disable-next-line:no-empty-interface
interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { }
class Component<P, S> {
    // tslint won't let me format the sample code in a way that vscode likes it :(
    /**
     * If set, `this.context` will be set at runtime to the current value of the given Context.
     *
     * Usage:
     *
     * ```ts
     * type MyContext = number
     * const Ctx = React.createContext<MyContext>(0)
     *
     * class Foo extends React.Component {
     *   static contextType = Ctx
     *   context!: React.ContextType<typeof Ctx>
     *   render () {
     *     return <>My context's value: {this.context}</>;
     *   }
     * }
     * ```
     *
     * @see https://reactjs.org/docs/context.html#classcontexttype
     */
    static contextType?: Context<any>;

    /**
     * If using the new style context, re-declare this in your class to be the
     * `React.ContextType` of your `static contextType`.
     *
     * ```ts
     * static contextType = MyContext
     * context!: React.ContextType<typeof MyContext>
     * ```
     *
     * @deprecated if used without a type annotation, or without static contextType
     * @see https://reactjs.org/docs/legacy-context.html
     */
    // TODO (TypeScript 3.0): unknown
    context: any;

    constructor(props: Readonly<P>);
    /**
     * @deprecated
     * @see https://reactjs.org/docs/legacy-context.html
     */
    constructor(props: P, context?: any);

    // We MUST keep setState() as a unified signature because it allows proper checking of the method return type.
    // See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257
    // Also, the ` | S` allows intellisense to not be dumbisense
    setState<K extends keyof S>(
        state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
        callback?: () => void
    ): void;

    forceUpdate(callBack?: () => void): void;
    render(): ReactNode;

    // React.Props<T> is now deprecated, which means that the `children`
    // property is not available on `P` by default, even though you can
    // always pass children as variadic arguments to `createElement`.
    // In the future, if we can define its call signature conditionally
    // on the existence of `children` in `P`, then we should remove this.
    readonly props: Readonly<{ children?: ReactNode }> & Readonly<P>;
    state: Readonly<S>;
    /**
     * @deprecated
     * https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
     */
    refs: {
        [key: string]: ReactInstance
    };
}

独自クラスの実装例。

index.html
<!-- 省略 -->
<script type="text/babel">

    type Props = {
      foo: string;
    }

    class MyComponent extends React.Component<props, {}> {
        render() {
            return <span>{this.props.foo}</span>
        }
    }

    ReactDOM.render(<MyComponent foo="bar" />, document.getElementById('root'));

</script>

React JSX Tip: Interface for renderable

React.ReactNode型を使用すると、レンダリング可能なインターフェイスとして使える。

index.html
<!-- 省略 -->
<script type="text/babel">
    type Props = {
        header: React.ReactNode;
        body: React.ReactNode;
    }

    class MyComponent extends React.Component<Props, {}> {
        render() {
            return <div>
                {this.props.header}
                {this.props.body}
            </div>;
        }
    }

    ReactDOM.render(<MyComponent header={<h1>Header</h1>} body={<i>body</i>} />, document.getElementById('root'));

</script>

React JSX Tip: Accept an instance of a Component

React.ReactElement<T> コンポーネントのインスタンスにアノテーションを付けられる。const foo = <MyAwesomeComponent />; で良い気もするけど、配列とかだと、ジェネリック型が効いてくるのかな?

index.html
<!-- 省略 -->
<script type="text/babel">
    class MyAwesomeComponent extends React.Component<Props, {}> {
        render() {
            return <div>Hello</div>;
        }
    }

    const foo: React.ReactElement<MyAwesomeComponent> = <MyAwesomeComponent />; // Okay
    //const bar: React.ReactElement<MyAwesomeComponent> = <NotMyAwesomeComponent />; // Error

    ReactDOM.render(foo, document.getElementById('root'));

</script>

続きは次回。

React JSX Tip: Accept a component that can act on props and be rendered using JSX

index.html
<!-- 省略 -->
<script type="text/babel">
    // 次回
</script>

React JSX Tip: Generic components

index.html
<!-- 省略 -->
<script type="text/babel">
    // 次回
</script>

Generic functions

index.html
<!-- 省略 -->
<script type="text/babel">
    // 次回
</script>

React Tip: Strongly Typed Refs

index.html
<!-- 省略 -->
<script type="text/babel">
    // 次回
</script>

Type Assertions

index.html
<!-- 省略 -->
<script type="text/babel">
    // 次回
</script>

Default Props

index.html
<!-- 省略 -->
<script type="text/babel">
    // 次回
</script>

感想

  • 調べながらだと時間かかる
  • 型がある世界は良い
  • 日本語の情報少ない?

以上

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2