差異處

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

連向這個比對檢視

web:reactjs:react_hook:usecontext [2019/02/24 23:57]
tony
web:reactjs:react_hook:usecontext [2023/06/25 09:48]
行 1: 行 1:
-====== React Hook - useContext ====== 
-===== Introduction ===== 
-我在Study React所撰寫的第一個範例是系統的登入與登出,而登入狀態需要由上層元件傳遞給登入與登出元件做修改。在這範例中,由於上層元件與登入元件只有一層,所以我可以透過建構元將狀態傳遞過去;然而登出元件與上層元件相差太多層,傳遞並不是那麼容易。\\ 
-\\ 
-在React Hook推出之前,有flux、Redux,或者是後來推出的Context,都可以解決這個問題;而本篇要介紹的useContext,我認為比前面幾個都還容易達到需求。 
-===== createContext ===== 
-<code javascript>​ 
-export const AuthContext = React.createContext(null);​ 
  
-function App(){ 
-  const [ state, setState ] = useState(false);​ 
- 
-  let route_target;​ 
-  if( !state ) { 
-    route_target = <Route path="/"​ name="​Login"​ component={LoginForm}/>;​ 
-  } else 
-    route_target = <Route path="/"​ name="​Home"​ component={DefaultLayout} />; 
- 
-  return ( 
-    <​AuthContext.Provider value={[state,​ setState]}>​ 
-      <​HashRouter>​ 
-        <​Switch>​ 
-        {route_target} 
-        </​Switch>​ 
-      </​HashRouter>​ 
-    </​AuthContext.Provider>​ 
-  ); 
-} 
-</​code>​ 
-===== useContext ===== 
-<​code>​ 
-function LoginForm(){ 
-  const [ authState, setAuthState ] = useContext(AuthContext);​ 
-  const [ username, setUserName ] = useState(""​);​ 
-  const [ password, setPassword ] = useState(""​);​ 
-  const [ feedback, setFeedBack ] = useState(null);​ 
- 
-  const validateForm = ()=>{ 
-    return username.length > 0 && password.length > 0; 
-  } 
- 
-  const handleSubmit = (e)=>{ 
-    e.preventDefault();​ 
-    try { 
-      Auth.signIn(username,​ password); 
-      setAuthState(true);​ 
-    } catch( err ) { 
-      setFeedBack(err.message);​ 
-    } 
-  } 
- 
-  const showFeedback = ()=>{ 
-    return feedback != null; 
-  } 
- 
-  return ( 
-    ​ 
-    <div className="​Login">​ 
-      <form onSubmit={handleSubmit}>​ 
-        <​FormGroup>​ 
-          <​Label>​Username</​Label>​ 
-          <Input 
-            autoFocus 
-            aria-label="​username-input"​ 
-            type="​text"​ 
-            value={username} 
-            onChange={e=>​setUserName(e.target.value)} 
-          ></​Input>​ 
-        </​FormGroup>​ 
-        <​FormGroup>​ 
-          <​Label>​Password</​Label>​ 
-          <Input 
-            value={password} 
-            aria-label="​password-input"​ 
-            onChange={e=>​setPassword(e.target.value)} 
-            type="​password"​ 
-          ></​Input>​ 
-        </​FormGroup>​ 
-        <Button 
-          block 
-          disabled={!validateForm()} 
-          type="​submit"​ 
-          onClick={()=>​{}} 
-        > 
-          Login 
-        </​Button>​ 
-        <br/> 
-        <Alert color="​danger"​ isOpen={showFeedback()} fade={true} aria-label="​feedback">​{feedback}</​Alert>​ 
-      </​form>​ 
-      ​ 
-    </​div>​ 
-  ); 
-} 
-</​code>​ 
-===== Unit Test ===== 
-<code java> 
-import {render, fireEvent, cleanup} from '​react-testing-library';​ 
-import React, { useState, useEffect } from '​react';​ 
-import LoginForm from '​../​LoginForm/​LoginForm';​ 
-import { AuthContext } from "​../​../​../​App";​ 
-import Auth from "​../​Components/​Auth/​Auth"​ 
- 
-let authState = false; 
-function LoginFormComp(){ 
-    const [ state, setState ] = useState(false);​ 
-    useEffect(()=>​{ 
-        authState = state; 
-    }); 
-    return <​AuthContext.Provider value={[state,​ setState]}><​LoginForm/></​AuthContext.Provider>;​ 
-} 
- 
- 
-describe('<​LoginForm/>',​()=>​{ 
-    afterEach(cleanup);​ 
- 
-    const inputLoginInfo = (utils, username, password)=>​{ 
-        const username_input = utils.getByLabelText('​username-input'​);​ 
-        const password_input = utils.getByLabelText('​password-input'​);​ 
- 
-        fireEvent.change(username_input,​ { 
-            target: { value: username } 
-        }); 
-        fireEvent.change(password_input,​ { 
-            target: { value: password } 
-        }); 
-    }; 
- 
-    const clickLoginBtn = (utils)=>​{ 
-        const loginButton = utils.getByText('​Login'​);​ 
-        fireEvent.click(loginButton);​ 
-    }; 
- 
-    const givenAuthSignInSuccessfully = ()=>{ 
-        const auth_do_nothing = jest.fn(); 
-        auth_do_nothing.mockImplementation(()=>​{});​ 
-        Auth.signIn = auth_do_nothing.bind(Auth);​ 
-    }; 
- 
-    it('​Login success',​ ()=>{ 
-        // given 
-        givenAuthSignInSuccessfully();​ 
-        const formComp = render(<​LoginFormComp/>​);​ 
- 
-         // when 
-         ​inputLoginInfo(formComp,​ '​ADMIN',​ '​ADMIN'​);​ 
-         ​clickLoginBtn(formComp);​ 
- 
-        // then 
-        expect(authState).toBeTruthy();​ 
-    }); 
-}); 
-</​code>​ 
-===== Reference ===== 
-  * [[https://​tinkerylabs.com/​react-context-api-with-hooks/​|React Context API + State Hook]] 
-  * [[https://​serverless-stack.com/​chapters/​who-is-this-guide-for.html|Learn to Build Full-Stack Apps with Serverless and React on AWS]] 
- 
-=====    ===== 
----- 
-\\ 
-~~DISQUS~~