programing

리액트 훅을 사용한 초기 상태로 리셋

topblog 2023. 2. 22. 21:30
반응형

리액트 훅을 사용한 초기 상태로 리셋

현재 등록 양식을 작성하고 있으며, 다음은 제 코드의 일부입니다.

const Signup = () => {
    const [username, setUsername] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [passwordConfirmation, setPasswordConfirmation] = useState('')

    const clearState = () => {
        setUsername('')
        setEmail('')
        setPassword('')
        setPasswordConfirmation('')
    }

    const handleSubmit = signupUser => e => {
        e.preventDefault()
        signupUser().then(data => {
            console.log(data)
            clearState() // <-----------
        })
    }

    return <JSX />
}

export default Signup

각 상태는 폼의 제어된 입력에 사용됩니다.

기본적으로 사용자가 정상적으로 등록한 후 필드를 클리어한 상태에서 상태를 초기 상태로 되돌리는 것입니다.

에서는 각 빈이 매우 합니다.clearStateReact에 포함되어 있는 상태를 초기값으로 리셋할 수 있는 메서드나 기능이 있는지 궁금합니다.

슬프게도 국가를 초기 가치로 설정할 수 있는 기본 제공 방법은 없습니다.

코드는 좋아 보이지만 필요한 기능을 줄이려면 전체 양식 상태를 단일 상태 변수 개체에 넣고 초기 개체로 재설정할 수 있습니다.

const { useState } = React;

function signupUser() {
  return new Promise(resolve => {
    setTimeout(resolve, 1000);
  });
}

const initialState = {
  username: "",
  email: "",
  password: "",
  passwordConfirmation: ""
};

const Signup = () => {
  const [
    { username, email, password, passwordConfirmation },
    setState
  ] = useState(initialState);

  const clearState = () => {
    setState({ ...initialState });
  };

  const onChange = e => {
    const { name, value } = e.target;
    setState(prevState => ({ ...prevState, [name]: value }));
  };

  const handleSubmit = e => {
    e.preventDefault();
    signupUser().then(clearState);
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>
          Username:
          <input value={username} name="username" onChange={onChange} />
        </label>
      </div>
      <div>
        <label>
          Email:
          <input value={email} name="email" onChange={onChange} />
        </label>
      </div>
      <div>
        <label>
          Password:
          <input
            value={password}
            name="password"
            type="password"
            onChange={onChange}
          />
        </label>
      </div>
      <div>
        <label>
          Confirm Password:
          <input
            value={passwordConfirmation}
            name="passwordConfirmation"
            type="password"
            onChange={onChange}
          />
        </label>
      </div>
      <button>Submit</button>
    </form>
  );
};

ReactDOM.render(<Signup />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

만, 리액트는 빌트인 리액트를 출시했습니다.useReducer말로 하면 '그것'이다.

행동에 대한 응답으로 나중에 상태를 재설정할 때 편리하다

https://reactjs.org/docs/hooks-reference.html#usereducer

또한 여러 하위 값을 포함하는 복잡한 상태 로직이 있는 경우 또는 다음 상태가 이전 상태에 따라 달라지는 경우 일반적으로 useReducer가 선호됩니다.

투표된 답변에 동일한 샘플을 사용하면 다음과 같이 useReducer를 사용할 수 있습니다.

자바스크립트

import React, { useReducer } from "react";

const initialState = {
    username: "",
    email: "",
    password: "",
    passwordConfirmation: "",
};

const reducer = (state, action) => {
    if (action.type === "reset") {
        return initialState;
    }

    const result = { ...state };
    result[action.type] = action.value;
    return result;
};

const Signup = () => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const { username, email, password, passwordConfirmation } = state;

    const handleSubmit = e => {
        e.preventDefault();

        /* fetch api */

        /* clear state */
        dispatch({ type: "reset" });
    };

    const onChange = e => {
        const { name, value } = e.target;
        dispatch({ type: name, value });
    };

    return (
        <form onSubmit={handleSubmit}>
            <div>
                <label>
                    Username:
                    <input value={username} name="username" onChange={onChange} />
                </label>
            </div>
            <div>
                <label>
                    Email:
                    <input value={email} name="email" onChange={onChange} />
                </label>
            </div>
            <div>
                <label>
                    Password:
                    <input
                        value={password}
                        name="password"
                        type="password"
                        onChange={onChange}
                    />
                </label>
            </div>
            <div>
                <label>
                    Confirm Password:
                    <input
                        value={passwordConfirmation}
                        name="passwordConfirmation"
                        type="password"
                        onChange={onChange}
                    />
                </label>
            </div>
            <button>Submit</button>
        </form>
    );
};

export default Signup;

타이프 스크립트

import React, { FC, Reducer, useReducer } from "react";

interface IState {
    email: string;
    password: string;
    passwordConfirmation: string;
    username: string;
}

interface IAction {
    type: string;
    value?: string;
}

const initialState: IState = {
    email: "",
    password: "",
    passwordConfirmation: "",
    username: "",
};

const reducer = (state: IState, action: IAction) => {
    if (action.type === "reset") {
        return initialState;
    }

    const result: IState = { ...state };
    result[action.type] = action.value;
    return result;
};

export const Signup: FC = props => {
    const [state, dispatch] = useReducer<Reducer<IState, IAction>, IState>(reducer, initialState, () => initialState);
    const { username, email, password, passwordConfirmation } = state;

    const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault();

        /* fetch api */

        /* clear state */
        dispatch({ type: "reset" });
    };

    const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const { name, value } = e.target;
        dispatch({ type: name, value });
    };

    return (
        <form onSubmit={handleSubmit}>
            <div>
                <label>
                    Username:
                    <input value={username} name="username" onChange={onChange} />
                </label>
            </div>
            <div>
                <label>
                    Email:
                    <input value={email} name="email" onChange={onChange} />
                </label>
            </div>
            <div>
                <label>
                    Password:
                    <input
                        value={password}
                        name="password"
                        type="password"
                        onChange={onChange}
                    />
                </label>
            </div>
            <div>
                <label>
                    Confirm Password:
                    <input
                        value={passwordConfirmation}
                        name="passwordConfirmation"
                        type="password"
                        onChange={onChange}
                    />
                </label>
            </div>
            <button>Submit</button>
        </form>
    );
};

「」는, 내가 입니다.reducer함수 const는 가능한 한 일반적이지만 완전히 변경하여 다양한 작업 유형(단순 상태 속성 이름 제외)을 테스트하고 복잡한 계산을 수행한 후 수정된 상태를 되돌릴 수 있습니다.을 사용하다

단답

이것은 매우 간단한 해결책이 있습니다.렌더링 컴포넌트의 주요 프로포넌트를 변경할 수 있습니다.예를 들어 편집할 컴포넌트가 있는 경우 이전 상태를 클리어하기 위해 다른 키를 사용할 수 있습니다.

return <Component key={<different key>} />

빠른 n' 더티 메서드를 원할 경우 컴포넌트의 키를 변경하기만 하면 React가 이전 컴포넌트 인스턴스를 마운트 해제하고 새 인스턴스를 마운트할 수 있습니다.

는 여기서 , Lodash는 Lodash ID, ID는 는 Lodash의 ID, ID는 Lodash의 입니다.Date.now()또는 이와 유사하며, 필요한 시간 분해능이 1밀리초 이상이라고 가정합니다.

를 두 있습니다.debugKey무슨 일이 일어나고 있는지 알기 쉽도록 하기 위해서입니다만, 이것은 필요 없습니다.

const StatefulComponent = ({ doReset, debugKey }) => {
  const [counter, setCounter] = React.useState(0);
  const increment = () => setCounter(prev => prev + 1); 
  return (
    <React.Fragment>
      <p>{`Counter: ${counter}`}</p>
      <p>{`key=${debugKey}`}</p>
      <button onClick={increment}>Increment counter</button>
      <button onClick={doReset}>Reset component</button>
    </React.Fragment>
  );
};

const generateUniqueKey = () => `child_${_.uniqueId()}`;

const App = () => {
  const [childKey, setChildKey] = React.useState(generateUniqueKey());
  const doReset = () => setChildKey(generateUniqueKey());
  return (
    <div className="App">
      <StatefulComponent key={childKey} debugKey={childKey} doReset={doReset} />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>


<div id="root"></div>

useRef를 다음과 같은 훅에 사용할 수 있습니다.

 const myForm = useRef(null)

 const submit = () => {

   myForm.current.reset(); // will reset the entire form :)

   }

  <form ref={myForm} onSubmit={submit}>

   <input type="text" name="name" placeholder="John Doe">

     <input type="email" name="name" placeholder="usman@gmail.com">

     <button type="submit">Submit</button>

 </form>

FAQ에 기재되어 있는 대로, 다음의 1개의 상태 변수를 사용할 수 있습니다.https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables

물론 사용 사례에 따라 다릅니다.

부모 컨테이너에서 컴포넌트를 키 재생성하면 당연히 자동으로 리셋됩니다.

다른 답변과 함께 이런 도우미 라이브러리를 선택하거나 자주 하게 될 경우 후크 위에 자신만의 추상화를 만들 것을 권장합니다.

useState그 위에 더 유용한 후크를 구축하기 위해 사용자인 당신에게 친구는 정말 낮은 수준의 기본 요소일 뿐입니다. 하는 .useState전화는 사실 꽤 드물어요.

훅을 했을 뿐이며, 「 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」resetState★★★★★★ 。

사용방법:

const [{
    foo: [foo, setFoo],
    bar: [bar, setBar],
  },
  resetState,
] = useStateWithReset({
  foo: null,
  bar: [],
})

// - OR -

const [
    [foo, setFoo],
    [bar, setBar],
  ],
  resetState,
] = useStateWithReset([
  null,
  [],
])

후자는 읽기 어렵지만 전자는 키를 복제하기 때문에 완벽한 해결책은 없습니다.

코드:

const useStateWithReset = initialState => {
  const hooksArray = Object.fromEntries(
    Object.entries(initialState).map(([k, v]) => {
      return [k, useState(v)]
    })
  );
  const resetState = () =>
    Object.entries(initialState).map(
      ([k, v]) => hooksArray[k][1](v)
    );
  return [hooksArray, resetState];
};

저도 비슷한 사용 사례가 있습니다.로그인, 등록 메커니즘과는 무관한 완전성입니다만, 고객님의 사용 사례에 관련되도록 변경했습니다.

이 문제를 해결하는 쉬운 방법은 부모 컴포넌트를 사용하는 것이라고 생각합니다.

const initUser = {
  name: '',
  email: '',
  password: '',
  passwordConfirmation: ''      
}

const LoginManager = () => {
  const [user, setUser] = useState(initUser)

  return <Signup user={user} resetUser={setUser} />
}

const Signup = ({user, resetUser}) => {
    const [username, setUsername] = useState(user.name)
    const [email, setEmail] = useState(user.email)
    const [password, setPassword] = useState(user.password)
    const [passwordConfirmation, setPasswordConfirmation] = useState(user.passwordConfirmation)


    const handleSubmit = signupUser => e => {
        e.preventDefault()
        signupUser().then(data => {
            console.log(data)
            resetUser(initUser) // <-----------
        })
    }

    return <JSX />
}

export default Signup

이 "초기 상태로 리셋"을 실현하는 방법 중 하나는 use-state-with-deps 패키지를 사용하는 것입니다.

예:

import {useStateWithDeps} from "use-state-with-deps";

const Signup = () => {
    const [generation, setGeneration] = useState(0);

    const [username, setUsername] = useStateWithDeps("", [generation])
    const [email, setEmail] = useStateWithDeps("", [generation])
    const [password, setPassword] = useStateWithDeps("", [generation])
    const [passwordConfirmation, setPasswordConfirmation] = useStateWithDeps("", [generation])

    const clearState = () => {
        setGeneration(generation + 1);
    }

    const handleSubmit = signupUser => e => {
        e.preventDefault()
        signupUser().then(data => {
            console.log(data)
            clearState()
        })
    }

    return <JSX />
}

export default Signup

새로운 의존관계를 도입하지 않으면 이 스레드에서 다른 솔루션을 찾을 수 있습니다.이 솔루션은 프로젝트에 직접 포함할 수 있을 정도로 짧습니다(예: "utils" 파일).예를 들어, 이 솔루션의 길이는 20줄에 불과합니다.

내가 알기로는 (리액션 문서를 읽음으로써) 아직 그렇게 할 방법이 없다.

useState는 다른 용도로 '포장'할 수 있습니다.원하는 이름]과(와) 리셋 기능을 포함합니다. 즉, Augustin이 답변에 제시한 커스텀 훅은 Augustin의 답변에 포함되어 있습니다.

입력 폼의 예를 들면, 다음과 같이 소스를 사용하고 표시할 수 있는 좋은 실제의 예가 있기 때문에, 다음과 같은 커스텀 훅을 사용합니다.

function ContactForm(props) {
  const [state, handleSubmit, reset] = useForm("contactForm");

  const clearForm = e => {
    e.preventDefault();
    reset();  // <---- the extra reset function
    // Any other code you want like hiding 
    // or removing the form div from the 
    // DOM etc.
  }

  if (state.succeeded) {
      return (
        <React.Fragment>
          <p>Thanks fro your input!</p>
          <button className="default-button" onClick={clearForm}>Ok</button>
        </React.Fragment>
      );
  }
  return (
      <form onSubmit={handleSubmit}> // <-- the standard setSate type function
      <label htmlFor="email" className="form-element">
        Email Address
      </label>
      <input
        id="email"
        type="email"
        name="email"
        className="form-element"
      />
      // etc - Your form code...
      <button className="default-button" type="submit" disabled={state.submitting}>
        Submit
      </button>
    </form>
  );
}

fomrspree git response react 예제(작성 시)에서 이를 확인할 수 있습니다. 함수는 useForm 소스에서 정의되며 'useForm.test.js'에서 사용되는 예가 있습니다.

GitHub와 NPM에는 많은 훅이 있으며, 그 중 몇 가지는 다음과 같습니다.

많은 훅 컬렉션을 나열했는데도 "is changed" 플래그가 있는 컬렉션을 찾을 수 없습니다.

양식 제출 후 후크에서 (오브젝트로부터의) 입력값을 리셋할 수 있습니다.

여러 입력 값을 동시에 정의할 수 있습니다.useStatefirstName, lastName...

const [state, setState] = React.useState({ firstName: "", lastName: "" });

샘플 코드

export default function App() {
  const [state, setState] = React.useState({ firstName: "", lastName: "" });
  const handleSubmit = e => {
    e.preventDefault();
    setState({firstName:'',lastName:''})
  };
  const handleChange = e => {
    const { name, value } = e.target;
    setState({ ...state, [name]: value });
  };
  console.log(state)
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        name="firstName"
        placeholder="Enter first name"
        value={state.firstName}
        onChange={handleChange}
      />
      <input
        type="text"
        name="lastName"
        placeholder="Enter last name"
        value={state.lastName}
        onChange={handleChange}
      />
      <input type="submit" value="Submit" />
    </form>
  );
}

개별적으로 선언하는 대신 개체에서 여러 입력을 정의하는 경우.

const handleSubmit = e => {
    e.preventDefault();
    reset();
}

언급URL : https://stackoverflow.com/questions/54895883/reset-to-initial-state-with-react-hooks

반응형