양식을 처리하기 위한 대체 지원 드릴링(역방향, 하위에서 상위로) 방식에 대응
<p>저는 React를 처음 접했고 실습 프로젝트를 통해 이를 배우고 있습니다. 저는 현재 양식 처리 및 유효성 검사 작업을 하고 있습니다. 저는 SPA에서 React Router의 Form 구성 요소를 사용하고 있으며 양식 내부에는 레이블 입력과 오류 메시지를 렌더링하는 FormGroup 요소가 있습니다. 또한 FormGroup 구성 요소 내에서 자체 입력 구성 요소를 사용하여 양식에 사용되는 입력의 논리와 상태 관리를 분리합니다. </p>
<p>그래서 샘플 로그인 페이지에 Form 구성 요소와 FormGroup 구성 요소를 다음과 같이 배치했습니다. </p>
<p><em>pages/Login.js</em></p>
<pre class="brush:js;toolbar:false;">'react'에서 { useState } 가져오기;
import { Link, Form, useNavigate, useSubmit } from 'react-router-dom';
'../comComponents/UI/FormGroup'에서 FormGroup을 가져옵니다.
'../comComponents/UI/Button'에서 버튼 가져오기;
'../comComponents/UI/Card'에서 카드를 가져옵니다.
import './Login.scss';
함수 로그인페이지() {
const Navigate = useNavigate();
const 제출 = useSubmit();
const [isLoginValid, setIsLoginValid] = useState(false);
const [isPasswordValid, setIsPasswordValid] = useState(false);
var 재설정LoginInput = null;
var 재설정PasswordInput = null;
isFormValid = false로 둡니다.
if(isLoginValid && isPasswordValid) {
isFormValid = true;
}
함수 formSubmitHandler(이벤트) {
event.preventDefault();
if(!isFormValid) {
반품;
}
재설정로그인입력();
ResetPasswordInput();
제출(event.currentTarget);
}
함수 loginValidityChangeHandler(isValid) {
setIsLoginValid(isValid);
}
함수 비밀번호ValidityChangeHandler(isValid) {
setIsPasswordValid(isValid);
}
함수 ResetLoginInputHandler(reset) {
ResetLoginInput = 재설정;
}
함수 재설정PasswordInputHandler(재설정) {
ResetPasswordInput = 재설정;
}
함수 스위치ToSignupHandler() {
탐색('/가입');
}
반품 (
<div className="로그인">
<div className="login__logo">
바둑컵
</div>
<p className="login__description">
바둑컵 계정에 로그인하세요
</p>
<카드 테두리>
<Form onSubmit={formSubmitHandler}>
<양식그룹
id="로그인"
label="사용자 이름 또는 이메일 주소"
inputProps={{
유형: "텍스트",
이름: "로그인",
유효성: (값) => {
값 = value.trim();
if(!값) {
return [false, '사용자 이름이나 이메일 주소가 필요합니다.']
} else if(값.길이 < 3 || 값.길이 > 30) {
return [false, '사용자 이름 또는 이메일 주소는 최소 3자 이상 최대 30자여야 합니다.'];
} 또 다른 {
return [참, null];
}
},
onValidityChange: loginValidityChangeHandler,
onReset: 재설정LoginInputHandler
}}
/>
<양식그룹
id="비밀번호"
label="비밀번호"
sideLabelElement={
<링크="/password-reset">
비밀번호를 잊으 셨나요?
</링크>
}
inputProps={{
유형: "비밀번호",
이름: "비밀번호",
유효성: (값) => {
값 = value.trim();
if(!값) {
return [false, '비밀번호가 필요합니다.']
} else if(값.길이 < 4 || 값.길이 > 1024) {
return [false, '비밀번호는 4자 이상, 최대 1024자여야 합니다.'];
} 또 다른 {
return [참, null];
}
},
onValidityChange: 비밀번호 유효성 변경 핸들러,
onReset: 재설정PasswordInputHandler
}}/>
<div className="text-center">
<버튼 클래스명="w-100" type="제출">
로그인
</버튼>
<span className="login__or">
또는
</스팬>
<버튼 클래스명="w-100" onClick={switchToSignupHandler}>
가입하기
</버튼>
</div>
</양식>
</카드>
</div>
);
}
기본 로그인 페이지 내보내기;
</pre>
<p>위 코드에서 볼 수 있듯이 FormGroup 구성 요소를 사용하고 <code>onValidityChange</code> 및 <code>onReset</code> 속성을 전달하여 <code>isValid< /코드의 업데이트된 값> 양식 제출 등 이후 입력 내용을 재설정하는 변경 및 재설정 기능 내 사용자 정의 후크 useInput을 사용하여 입력 구성 요소에 <code>isValid</code> 및 <code>reset</code> 값이 변경되면 isValid 값을 전달하고 FormGroup 구성 요소에 정의된 props를 사용하여 입력 구성 요소에서 재설정 함수를 전달합니다. 또한 로그인 페이지에서 <code>isLoginValid</code> 및 <code>isPasswordValid</code> 상태를 사용하여 하위 입력에서 전달된 업데이트된 <code>isValid</code> 요소. 그래서 입력 컴포넌트에 상태를 정의하고 props를 사용하여 이를 부모 컴포넌트에 전달하고 그 값을 해당 부모 컴포넌트에서 생성된 다른 상태에 저장했습니다. 진행되고 있는 소품 드릴링이 조금 불편했습니다. </p>
<p>상태는 입력 구성 요소 내부에서 관리되며 다음과 같은 상태를 갖습니다. </p>
<li><strong>값: </strong>요소의 값을 입력합니다. </li>
<li><strong>isInputTouched</strong>: 유효성 검사 오류 메시지가 있는 경우 표시할지 여부를 결정하기 위해 사용자가 입력을 터치/초점했는지 여부를 결정합니다. </li>
</ul>
<p>일부 기능(예: 입력 구성 요소에 전달된 유효성 검사 기능)을 이 두 상태에 결합하고 적용하여 다른 변수 값을 생성하여 입력 및 해당 값의 유효성(예: 값이 유효한지 여부)에 대한 정보를 수집합니다. (isValid ), 확인 메시지(message)가 있는지, 입력이 유효한지(<code>isInputValid = isValid || !isInputTouched</code>) 확인 메시지를 표시할지 결정합니다.</p>
<p>이러한 상태와 값은 제가 만든 사용자 정의 후크인 <code>useInput</code>에서 다음과 같이 관리됩니다. </p>
<p><em>hooks/use-state.js</em></p>
<pre class="brush:js;toolbar:false;">import { useState, useCallback } from 'react';
함수 useInput(validityFn) {
const [value, setValue] = useState('');
const [isInputTouched, setIsInputTouched] = useState(false);
const [isValid, 메시지] = 유효성Fn 유형 === '함수' ? 유효성Fn(값) : [true, null];
const isInputValid = isValid ||
const inputChangeHandler = useCallback(event => {
setValue(event.target.value);
if(!isInputTouched) {
setIsInputTouched(true);
}
}, [isInputTouched]);
const inputBlurHandler = useCallback(() => {
setIsInputTouched(true);
}, []);
const 재설정 = useCallback(() => {
setValue('');
setIsInputTouched(false);
}, []);
반품 {
값,
유효하다,
isInputValid,
메시지,
입력ChangeHandler,
입력BlurHandler,
초기화
};
}
기본 useInput 내보내기;
</pre>
<p>저는 현재 다음과 같이 Input.js에서 이 사용자 정의 후크를 사용하고 있습니다. </p>
<p><em>comComponents/UI/Input.js</em></p>
<pre class="brush:js;toolbar:false;">'react'에서 { useEffect }를 가져옵니다.
'../../hooks/use-input'에서 useInput을 가져옵니다.
import './Input.scss';
함수 입력(소품) {
const {
값,
유효하다,
isInputValid,
메시지,
입력ChangeHandler,
입력BlurHandler,
초기화
} = useInput(props.validity);
const {
onIsInputValidOrMessageChange,
유효성 변경,
재설정 시
} = 소품;
let className = '양식 제어';
if(!isInputValid) {
className = `${className} 양식-제어--잘못됨`;
}
if(props.className) {
className = `${className} ${props.className}`;
}
useEffect(() => {
if(onIsInputValidOrMessageChange && typeof onIsInputValidOrMessageChange === '함수') {
onIsInputValidOrMessageChange(isInputValid, 메시지);
}
}, [onIsInputValidOrMessageChange, isInputValid, 메시지]);
useEffect(() => {
if(onValidityChange && typeof onValidityChange === '함수') {
onValidityChange(isValid);
}
}, [onValidityChange, isValid]);
useEffect(() => {
if(onReset && typeof onReset === '함수') {
onReset(리셋);
}
}, [onReset, 재설정]);
반품 (
<입력
{...소품}
클래스이름={클래스이름}
값={값}onChange={inputChangeHandler}
onBlur={inputBlurHandler}
/>
);
}
기본 입력 내보내기;
</pre>
<p>입력 구성 요소에서 <code>isInputValid</code> 상태를 직접 사용하여 잘못된 CSS 클래스를 입력에 추가했습니다. 하지만 <code>isInputValid</code>, <code>message</code>, <code>isValid</code> 및 <code>reset</code> 함수도 상위 구성 요소에 전달합니다. 그것에 사용합니다. 이러한 상태와 함수를 전달하기 위해 소품에 정의된 <code>onIsInputValidOrMessageChange</code>, <code>onValidityChange</code>, <code>onReset</code> 함수를 사용합니다. 대신에 from 자녀가 부모에게). </p>
<p>다음은 FormGroup 구성 요소의 정의이며 FormGroup 내부의 입력 상태를 사용하여 유효성 검사 메시지(있는 경우)를 표시하는 방법입니다. </p>
<p><em>comComponents/UI/FormGroup.js</em></p>
<pre class="brush:js;toolbar:false;">'react'에서 { useState } 가져오기;
'./Input'에서 입력 가져오기;
import './FormGroup.scss';
함수 FormGroup(props) {
const [message, setMessage] = useState(null);
const [isInputValid, setIsInputValid] = useState(false);
let className = '양식-그룹';
if(props.className) {
className = `양식 그룹 ${props.className}`;
}
labelCmp = (
<label htmlFor={props.id}>
{props.label}
</라벨>
);
if(props.sideLabelElement) {
labelCmp = (
<div className="form-label-group">
{labelCmp}
{props.sideLabelElement}
</div>
);
}
함수 isInputValidOrMessageChangeHandler(changedIsInputValid,changeMessage) {
setIsInputValid(changedIsInputValid);
setMessage(changedMessage);
}
반품 (
<div className={className}>
{labelCmp}
<입력
id={props.id}
onIsInputValidOrMessageChange={isInputValidOrMessageChangeHandler}
{...props.inputProps}
/>
{!isInputValid <p>{메시지}</p>}
</div>
);
}
기본 FormGroup 내보내기;
</pre>
<p>위 코드에서 볼 수 있듯이 업데이트된 <code>message</code> <code>isInputValid</code> code> 입력 구성 요소에서 전달된 상태입니다. 이러한 값을 유지하기 위해 입력 구성 요소에 2개의 상태를 정의했지만 업데이트되고 전달된 값을 입력 구성 요소에 저장하려면 이 구성 요소에 또 다른 2개의 상태를 정의해야 합니다. 이것은 약간 이상하고 나에게 가장 좋은 방법이 아닌 것 같습니다. </p>
<p><strong>질문은: </strong>여기서 소품 드릴링 문제를 해결하기 위해 React Context(useContext) 또는 React Redux를 사용할 수 있다고 생각합니다. 하지만 현재 상태 관리가 좋지 않고 React Context 또는 React Redux를 사용하여 개선할 수 있는지 잘 모르겠습니다. 내가 이해한 바로는 상태가 자주 변경되는 상황에서는 React Context가 끔찍할 수 있지만 Context가 애플리케이션 전체에서 사용된다면 이것이 작동합니다. 여기에서는 전체 양식을 저장하고 업데이트하는 컨텍스트를 생성하여 양식 전체를 확장할 수 있습니다. 반면에 React Redux는 사일로에 가장 적합하지 않을 수 있으며 약간 과잉일 수도 있습니다. 어떻게 생각하나요? 이 특별한 상황에 대해 더 나은 대안은 무엇입니까? </p>
<p><strong>참고: </strong>저는 React를 처음 접하기 때문에 단순한 실수부터 일반적인 실수까지 모든 코딩에 대한 여러분의 제안에 열려 있습니다. 감사해요! </p>