1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
// reducerFn寫在元件外面,相關參數會透過dispatch傳入
const emailReducer = (state, action) => {
// 收到dispatch事件同時更新input值跟isValid狀態
if (action.type === 'USER_INPUT') {
return { value: action.value, isValid: action.value.includes('@') };
}
// 點其他Input會Blur
if (action.type === 'INPUT_BLUR') {
// 這邊Blur事件不會傳遞值,但需要有一個值維持狀態
// state.value可以拿到最新的state
return { value: state.value, isValid: state.value.includes('@') };
// includes驗證會回傳true false
}
return { value: '', isValid: false };
};
const passwordReducer = (state, action) => {
if (action.type === 'USER_INPUT') {
return { value: action.value, isValid: action.value.trim().length > 6 };
}
// 點其他Input會Blur
if (action.type === 'INPUT_BLUR') {
// 這邊Blur事件不會傳遞值,但需要有一個值維持狀態
// state.value可以拿到最新的state
return { value: state.value, isValid: state.value.trim().length > 6 };
// includes驗證會回傳true false
}
return {value:'', isValid: false}
}
const Login = (props) => {
// const [enteredEmail, setEnteredEmail] = useState('');
// const [emailIsValid, setEmailIsValid] = useState();
// const [enteredPassword, setEnteredPassword] = useState('');
// const [passwordIsValid, setPasswordIsValid] = useState();
const [formIsValid, setFormIsValid] = useState(false);
const [emailState, dispatchEmail] = useReducer(emailReducer, {
value: '',
isValid: null,
});
// 上面是initState
const [passwordState, dispatchPassword] = useReducer(passwordReducer, {
value:'', isValid: null
})
useEffect(() => {
console.log('EFFECT RUNNING');
return () => {
console.log('EFFECT CLEANUP');
};
}, []);
// 解構賦值,改換另一個變數名
const { isValid: emailIsValid } = emailState;
const { isValid: passwordIsValid } = passwordState;
useEffect(() => {
const identifier = setTimeout(() => {
console.log('Checking form validity!');
setFormIsValid(emailIsValid && passwordIsValid);
}, 500);
return () => {
console.log('CLEANUP');
clearTimeout(identifier);
};
// 改由驗證有更新再re-run effect來優化效能
}, [emailIsValid, passwordIsValid]);
const emailChangeHandler = (event) => {
// 通常是一個物件 {type:'', 也可以寫payload要跟上面reducer action內key值一樣: 傳遞下去的值}
dispatchEmail({type: 'USER_INPUT', value: event.target.value});
setFormIsValid(
event.target.value.includes('@') && enteredPassword.trim().length > 6
);
};
const passwordChangeHandler = (event) => {
dispatchPassWord({type:'USER_INPUT', value:event.target.value})
setFormIsValid(
emailState.isValid && event.target.value.trim().length > 6
);
};
const validateEmailHandler = () => {
dispatchEmail({type: 'INPUT_BLUR'});
};
const validatePasswordHandler = () => {
dispatchPassword({type: 'INPUT_BLUR'});
};
const submitHandler = (event) => {
event.preventDefault();
// state取值用state.value
props.onLogin(emailState.value, passwordState.value);
};
|