差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

下次修改
前次修改
web:reactjs:react_hook:usestate [2019/02/22 21:16]
tony 建立
web:reactjs:react_hook:usestate [2023/06/25 09:48] (目前版本)
行 1: 行 1:
 +{{tag>​reactjs}}
 ====== React Hook - useState ====== ====== React Hook - useState ======
 +===== Introduction =====
 +從我研究React到現在,我認為React是基於state去決定UI該怎麼呈現。在2018年React提出了Hook,賦予了Function Component擁有了React State的概念。我以大家最常使用的Counter範例,來分享用法。一個Counter UI,它透過div顯示次數,透過點擊button去增加次數;在使用React Component的寫法時,程式碼如下,你必須透過this.state宣告member,而透過setState告知React狀態的改變:​
 +<code javascript>​
 +import React, { Component } from "​react"​
  
 +class CounterComp extends Component {
 +    constructor(prop){
 +        super(prop);​
 +        this.state = { count: 0 };
 +    }
 +
 +    render(){
 +        const { count } = this.state;
 +        return (
 +            <>
 +                <div aria-label="​counter-val">​This is a example: {count}.</​div>​
 +                <button onClick={() => { this.setState({ count: count + 1 }); }}>​count+1</​button>​
 +            </> ​   ​
 +        );
 +    }
 +}
 +
 +export default CounterComp
 +</​code>​
 +只要你做了setState後,相關的元件就會做出對應的改變。接下來的文章將分享如何改成useState的形式與對應測試該怎麼寫。
 +===== useState =====
 +首先看看程式碼量的差異:​
 +<code javascript>​
 +import React, { useState } from "​react"​
 +
 +function CounterFunc() {
 +    const [ count, setCount ] = useState(0);​
 +
 +    return (
 +        <>
 +            <div aria-label="​counter-val">​This is a example: {count}.</​div>​
 +            <button onClick={()=>​setCount(count+1)}>​count+1</​button>​
 +        </>
 +    )
 +}
 +
 +export default CounterFunc
 +</​code>​
 +首先透過useState賦予count預設值,內容也可以是json;而setCount是用來修改count的狀態。接著在button中綁定一個函式,呼叫setCount並把新的值設定進去即可。是不是很簡單?​
 +===== Unit Test =====
 +一開始我使用了enzyme去測試改完的程式碼:​
 +<code javascript>​
 +it('​Test click button of counterFunc',​ ()=>{
 +    const counterFunc = shallow(<​CounterFunc/>​);​
 +    counterFunc.find('​button'​).simulate('​click'​);​
 +    expect(counterFunc.find('​div'​).text()).toBe('​This is a example: 1.');
 +});
 +</​code>​
 +但我發現click並無法觸發狀態的改變。爬一下文,發現這目前是enzyme的問題[[https://​github.com/​reactjs/​rfcs/​issues/​71|link]],也許以後某天會改。因此我改用react-testing-library做測試:​
 +<code javascript>​
 +import CounterFunc from "​../​CounterFunc";​
 +import {render, fireEvent, cleanup} from '​react-testing-library';​
 +import React from '​react';​
 +import renderer from '​react-test-renderer';​
 +import {shallow} from '​enzyme';​
 +
 +
 +describe('<​CounterFunc>',​()=>​{
 +    afterEach(cleanup);​
 +
 +    it('​CounterFunc snapshot',​ () => {
 +        const tree = renderer.create(<​CounterFunc/>​).toJSON()
 +        expect(tree).toMatchSnapshot();​
 +    })
 +
 +    // //​Can'​t work with React-Hook
 +    // it('​Test click button of counterFunc',​ ()=>{
 +    //     const counterFunc = shallow(<​CounterFunc/>​);​
 +    //     ​counterFunc.find('​button'​).simulate('​click'​);​
 +    //     ​expect(counterFunc.find('​div'​).text()).toBe('​This is a example: 1.');
 +    // });
 +
 +    it('​Test click button of counterFunc',​ ()=>{
 +        const utils = render(<​CounterFunc/>​);​
 +        const display = utils.getByLabelText('​counter-val'​);​
 +        const button = utils.getByText('​count+1'​);​
 +
 +        fireEvent.click(button);​
 +        expect(display.textContent).toBe('​This is a example: 1.');
 +    });
 +});
 +</​code>​
 +===== Reference =====
 +  * [[https://​reactjs.org/​docs/​hooks-state.html|reactjs - hooks state]]
 +  * [[https://​jestjs.io/​docs/​en/​getting-started|jest - getting-started]]
 +
 +=====    =====
 +----
 +\\
 +~~DISQUS~~