State


詳細コードの表示
ex04: Component - React State
01.基本概念
02.制御素子/非制御素子
03.ステータスエレメントとPureエレメント(バカ、Dumb)
04. Data Flow(Bottom-Up)
Run examples
$ npm run debug src={no}
01.基本概念
Stateバー

  • 構成部品内部の現在のステータスを示す書き込み可能な管理データ
  • データフォーマットは関係ありません.

  • ステータスの変更によりUIが再レンダリングされます.

  • クラス構成部品はconductorによってdefault値セットとして作成されます.

  • 関数構成部品はuserStateという名前のフック関数を使用して初期化されます.

  • 基本的にはユーザイベントに変更したり、通信に変更したりすることができます.

  • 構成部品はthisです.state内には複数のデータがあります.(class component)

  • this.stateは特定の構成部品のデータであり、setState()関数を使用して変更されます.(class component)

  • ステータスが更新されると、構成部品の「反転」(Reactive)レンダリングがトリガーされ、構成部品とサブ構成部品が再レンダリングされます.
  • 素子内部の状態を最低限に保つことが望ましい.
  • 構成部品内部の状態を正確に外部に表示し、インタフェースを同期させるために再レンダリングします.

  • コンポーネントがアクション(イベント)とインタラクティブになるメカニズムを提供します.

  • 親の状態が変化した場合は、子の状態を再読み込みします.

  • Top-Down property伝達はデータストリームの構造化方法である.

  • Boottom-Up Flowにデータを渡す場合は、属性ではなくコールバック関数を使用します.

  • なぜ素子の構造化を設計し、stateコンポーネントを関連する素子に組み合わせて親化するのか.すべてを1つのstateコンポーネントに配置すると、表示範囲が広くなるため、部分的に包装処理を行う必要がある.レンダリングされた部分を細かくし、最大限に構造化することが望ましい.

  • begin(初期値)step(インクリメンタル)をpropsに渡し、イベント発生時に初期値を増加させる例

  • Class Component
  • クラスはconstructorでpropsを設定できます.
  • stateは、値をオブジェクトに設定する必要があります.
  • import React, {Component} from 'react';
    
    export default class extends Component{
        constructor(){
            super(...arguments);
            this.state = {
                value: this.props.begin
            }
        }
        onClickEventHandler() {
            // this.state.value = this.state.value + this.props.step
            // 위와 같이 하면 렌더가 되지 않는다. 
    
            this.setState({
                value: this.state.value + this.props.step
            });
        }
        render(){
            return(
                <div>
                    <button onClick={ this.onClickEventHandler.bind(this) }>
                        <strong>+</strong>
                    </button>
                    { '  ' }
                    <span>{ this.state.value }</span>
                </div>
            )
        }
    }
    

  • function Component
  • usStateフック関数
  • フック関数は、アクセス可能な値の名前と変更可能な値の関数を放出します.
  • import React, { useState } from 'react';
    
    export default function({ begin, step }){
        const [ value, setValue ] = useState(begin); 
    // 값에 접근할 수 있는 이름과, 값을 변경할 수 있는 함수를 던져준다.
    // 배열의 객체 분해를 활용한다.
    // props 또한 객체 분해를 활용하여 가독성을 높인다. 
    
        const onClickEventHandler = function() {
            setValue( value + step );
        }
    
    return(
        <div>
            <button onClick={ onClickEventHandler }>
                <strong>+</strong>
            </button>
            { '  ' }
            <span>{ value }</span>
        </div>
    )
    }
    02.制御素子
  • formの入力値は制御可能であることが望ましい.
  • <input>, <textarea>, <option>などのフォームコンポーネントで、ユーザーの入力に応じてステータス値を変更してレンダリングするコンポーネントを「コントロール」コンポーネントと呼びます.
  • フォームコンポーネントは、必ずしも制御コンポーネントとして記述される必要はありません.非制御状態の非制御構成部品として作成することもできます.(Anti-Pattern)
  • フォームコンポーネントを制御コンポーネントとして作成するのは複雑ですが、次のような利点があります.
  • Reactのコンポーネント作成の原則は、コンポーネントのインタフェースを外部から直接変更するのではなく、内部状態の変更で完了することです.
  • Validation.
  • [src/02]制御素子
  • font-awesomeを使用
  • font-awesomeコメント
  • import React, { useState } from 'react';
    import './assets/Form.css';
    import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
    import { faCheckCircle, faTimesCircle } from '@fortawesome/free-solid-svg-icons';
    
    export default function Form() {
        const [name, setName] = useState('');
        const [email, setEmail] = useState('');
        const [validEmail, setValidEmail] = useState(false);
        const [password, setPassword] = useState('');
        const [gender, setGender] = useState('female');
        const [bithYear, setbirthYear] = useState(1984);
        const [selfDescription, setSelfDescription] = useState('');
        const [agreeProv, setAgreeProv] = useState('no');
    
    
        const onChangeInputName = function(e) {
            // setName(e.target.value);
            // 10 자 제한(Validation)
            setName(e.target.value.substr(0,10));
        }
        const onChangeInputEmail =  function (e){
            setEmail(e.target.value);
    
            const re = /[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]$/i;
            // Ajax
            // const result = await fetch('/user/emailcheck?email' + e.target.value);
            // setValidEmail(!result.data);
            setValidEmail(re.test(e.target.value));
        }
        const onChangeInputPassword = function(e){
            setPassword(e.target.value.substr(0,10));
        }
    
        const onChangeInputGender = function (e){
            setGender(e.target.value);
        }
    
        const onChangeInputProv = function (e){
        //    API 호출
            const url = `/prov/agree?status=${e.target.value === 'no' ? 'yes' : 'no'}`;
            console.log(url);
            if(true){
                setAgreeProv(e.target.value === 'no' ? 'yes' : 'no');
            }
        }
    
        return (
            <form id="joinForm" name="joinForm" method="post" action="/do/not/post">
                {/* name */}
                <label htmlFor="name">이름</label>
                <input id="name" name="name" type="text" value={name} onChange={onChangeInputName}/>
    
                {/* email */}
                <label htmlFor="email">이메일</label>
                <input id="email" name="email" type="text" value={email} onChange={onChangeInputEmail}/>
                {/* etc */}
                {
                    email === '' ? null :
                        validEmail ?
                            <FontAwesomeIcon icon={faCheckCircle} style={{marginLeft: 5, color: 'blue'}} size='lg'/> :
                            <FontAwesomeIcon icon={faTimesCircle} style={{marginLeft: 5, color: 'red'}} size='lg'/>
                }
    
                {/* password */}
                <label htmlFor="password">패스워드</label>
                <input id="password" name="password" type="password" value={password} onChange={onChangeInputPassword}/>
    
                {/* gender, radio box */}
                <fieldset>
                    <legend>성별</legend>
                    <label></label> <input type="radio" name="gender" value={"female"} checked={gender === 'female'} onChange={ onChangeInputGender }/>
                    <label></label> <input type="radio" name="gender" value={"male"} checked={ gender === 'male'} onChange={ onChangeInputGender }/>
                </fieldset>
    
                {/* select/options */}
                <label htmlFor="birthYear">생년</label>
                <select id="birthYear" name='birthYear' value={ bithYear } onChange={ e => setbirthYear(e.target.value) }>
                    <option value={ 1984 }>1984</option>
                    <option value={ 1985 }>1985</option>
                    <option value={ 1986 }>1986</option>
                    <option value={ 1987 }>1987</option>
                    <option value={ 1988 }>1988</option>
                    <option value={ 1989 }>1989</option>
                    <option value={ 1990 }>1990</option>
                </select>
    
                {/* textarea */}
                <label htmlFor="birthYear">자기소개</label>
                <textarea id='selfDescription' name='selfDescription' value={ selfDescription } onChange={ e => setSelfDescription(e.target.value.substr(0,50))}/>
    
    
                <fieldset>
                    <legend>약관동의</legend>
                    <input
                        id="agree-prov"
                        type="checkbox"
                        name="agreeProv"
                        value={ agreeProv }
                        checked={ agreeProv === 'yes'}
                        onChange={ onChangeInputProv }
                    />
                    <label>서비스 약관에 동의합니다.</label>
                </fieldset>
    
                <input type="submit" value="가입"/>
            </form>
        );
    }
    [src/03]非制御素子
    03.ステータスエレメントとPureエレメント(バカ、Dumb)

  • Stateful Comonent
  • 管理状態のコンポーネント
  • 通常の状態を管理する構成部品は、構成部品階層の上部にあります.
  • Top -> Down
  • 通常の状態要素は、1つまたは複数の純粋な要素を包装することができる.

  • Pure Component
  • ステータスを考慮せずに、プロパティ(props)のみを使用して画面のコンポーネントをレンダリングします.
  • 再利用可能であり、テストが容易である.

  • アプリケーションの構成部品は、ステータス構成部品と純粋な構成部品に分離することが望ましい.

  • どの構成部品がステータス構成部品であるかを知る()
  • ステータスに基づいて登録されたコンポーネント
  • 多数のサブエレメントを含む共通の(1つの)親エレメント
  • 構成部品階層の上部にあり、ステータスでなければならない構成部品
  • 見つからない場合は、管理状態の構成部品を作成し、サブ(純粋な)構成部品をカプセル化します.
  • 例)Emairlist(list part,props)
    emaillist
    04. Data Flow(Bottom-Up)
  • reactionアプリケーションのデータが素子層top->Downを介してpropsを伝達することはデータストリームの基本メカニズムである
  • Kingchiただし、ほとんどのアプリケーションがBoottom-Upにデータを送信する必要があります.
  • 例)Emairlist(search part,callback)
    emaillist