お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。
投稿日:
ライブラリ::Jinja言語::Python

substring

確認環境

Env Ver
Jinja 2.11.0
Python 3.8.5

サンプルコード

  • 変数名[begin:end]で指定する
    • {% set some_variable = string_variable[0:100] %}

ループ処理で変数代入を行う

確認環境

Env Ver
Jinja 2.11.0
Python 3.8.5
  • Jinja2でループ処理の中で変数の足しこみとかをするやつ
    • 代入先の変数宣言は{% set ns = namespace(title = "") %}のようにしてやる必要がある
    • 後はループの中でsetしてやれば上手くいく
    • 変数は宣言したブロックがスコープになるので、スコープを広げたいときは適当にブロックを上げてやると良い

サンプルコード

  • MkDocsのテンプレートでパンくずリストを生成するコード
    • [A] [B] [C]みたいな感じ
{% set ns = namespace(title = "") %}
{% for doc in page.ancestors %}
    {% set ns.title = "[" + doc.title + "] " + ns.title %}
{% endfor %}

テンプレートファイルを読み込む

確認環境

Env Ver
Jinja 2.11.0
Python 3.8.5

サンプルコード

  • フォルダ構成
─src
    ├─app
    │   ├─configs
    │   │    └config.yaml
    │   ├─templates
    │   │         └─main.html
    │   └─__init__.py
    └─main.py
  • コード
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
    # appはフォルダ構成のappフォルダを指す
    loader=PackageLoader('app', 'templates'),
    autoescape=select_autoescape(['html', 'xml'])
)
template = env.get_template('main.html')
# `render()` の引数は埋め込み変数を KeyValue 形式で指定
print(template.render(the='variables', go='here'))

yamlファイルから設定をロードする

確認環境

Env Ver
Jinja 2.11.0
Python 3.8.5

サンプルコード

  • フォルダ構成
─src
    ├─app
    │   ├─configs
    │   │    └config.yaml
    │   ├─templates
    │   │         └─main.html
    │   └─__init__.py
    └─main.py
  • コード
from yaml import safe_load as yamlLoad
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
    loader=PackageLoader('app', 'templates'),
    autoescape=select_autoescape(['html', 'xml'])
)

template = env.get_template('main.html')
with open('app/configs/config.yaml') as fYaml:
    print(template.render(yamlLoad(fYaml)))

概要

  • Jinja2で作られている
    • Python向けのテンプレートエンジン
    • これを理解することで自在にカスタマイズできる。たぶん
  • テンプレート変数について、まともなリファレンスはないので、mkdocsのGitHubリポジトリを眺めて知るのが早い
    • www.mkdocs.org にも一応書いてあるが、網羅されていない

カスタマイズ方法

  • まずはMaterial for MkDocsを読んでリファレンスを理解する
    • 設定で解決する内容ならここで終わり
  • テンプレートのカスタマイズが必要な場合、overrides/main.htmlを生やしてブロック単位でいじる

フックを単体でテストするケースを想定。

このパターンはコンポーネントからフックを切り離しているケースで有用。手法としては@testing-library/react-hooksrenderHook()を使う。

カスタムフック

export const useUserForm = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const onChangeUserName = (ev: string) => {
    setUsername(ev);
  };
  const onChangePassword = (ev: string) => {
    setPassword(ev);
  };

  return {
    username,
    password,
    onChangeUserName,
    onChangePassword,
  };
};

テストコード

it('onChangeUserName で username が設定されること', () => {
  // `renderHook` で Hook をレンダリング
  const { result } = renderHook(() => useUserForm());
  // `act()` で Hook のイベントを叩く
  act(() => result.current.onChangeUserName('foo'));
  // 結果を見る
  expect(result.current.username).toBe('foo');
});
投稿日:
ライブラリ::React言語::TypeScript

TSの情報に乏しく無駄にハマったのでメモ程度に

確認環境

Env Ver
React 17.0.1
TypeScript 4.1.3

サンプルコード

  • 今回はサンプルとして<input />をラップしたコンポーネントのフォーカスを変更するためにrefを使います

Child.tsx

import { forwardRef } from 'react';

export type ChildProps = {
  type: 'text' | 'password' | 'number';
  onChange(changeValue: string): void;
};

// function 記法でないと ESLint が怒るので無効化
// eslint-disable-next-line react/display-name
export const Child = forwardRef<HTMLInputElement, ChildProps>(
  // このpropsに明示的な型定義がないと型エラーが出る
  (props: ChildProps, ref) => {
    const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
      props.onChange(ev.target.value);
    };

    return (
      <input
        ref={ref}
        type={props.type}
        onChange={(ev) => onChange(ev)}
      />
    );
  }
);

Parent.tsx

  • 下側の<Child />だけフォーカスが行くようにしてます
import { useEffect, useRef } from 'react';
import { Child } from './Child';

export const Parent = () => {
  const ref = useRef<HTMLInputElement>(null);
  useEffect(() => {
    ref?.current?.focus();
  }, []);
  return (
    <ul>
      <li>
        <Child
          type={'text'}
          onChange={(ev) => console.log('top input', ev)}
        />
      </li>
      <li>
        <Child
          ref={ref}
          type={'text'}
          onChange={(ev) => console.log('bottom input', ev)}
        />
      </li>
    </ul>
  );
};