簡體   English   中英

如何讓 setState 在功能性 React 組件的事件處理程序中工作

[英]How can i get setState to work in an event handler in a functional React component

我正在重構一個 MERN 應用程序以使用鈎子和上下文,因此我將 class 組件更改為函數。 一個組件有一個表單,它根據輸入字段中的擊鍵來更改 state,例如:

    class CreateAccountComp extends Component {
      constructor(props) {
      super(props);

      this.state = {
        firstName: null,
        lastName: null,
        email: null,
        password: null,
        githubID: null,
    };
  }

  handleSubmit = (e) => {
    e.preventDefault();
    this.props.handleInputChange();
    API.getsync(this.state.githubID, this.state.firstName, this.state.lastName, this.state.email);
    ...
    })
  };

  handleChange = (e) => {
    e.preventDefault();
    const { name, value } = e.target;
    ...
    this.setState({ [name]: value }, () => null);
  };
  ....

這在將回調添加到“this.setState”語句后起作用。

新組件如下所示:

const CreateAccountComp = (props) => {

  const [state, setState] = useState({
    firstName: null,
    lastName: null,
    email: null,
    password: null,
    githubID: null,
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log("HMMMM leaving CreateAccountcomp");
    props.handleInputChange();
    API.getsync(state.githubID, state.firstName, state.lastName, state.email);
    ...
  };

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

現在,我不能使用回調來處理異步setState語句,並且傳遞給API.getsync() function 的 state 屬性是未定義的。

我的研究提出了使用 async/await 或 useEffect 的示例,但它們都處理對外部 api 的單個調用。 在這里,我正在運行handleChange以將擊鍵呈現到表單中的輸入字段中,然后通過onSubmit運行handleSubmit以執行 function 以根據 state 值更新數據庫。 有沒有辦法在這個 function 組件中正確更新 state ?

您可以使用useEffect掛鈎並將state作為依賴項添加到useEffect掛鈎,以便在每次state object 更改時運行

useEffect(() => {
    // code to run every time `state` object changes
    API.getsync(state.githubID, state.firstName, state.lastName, state.email);
}, [state]);

您也沒有正確更新 state。 Unlike this.setState , which this.setState the previous state with the new one, function returned by useState hook will overwrite the previous state with the new state.

為避免覆蓋 state,請確保手動將以前的 state 與新的合並

const handleChange = (e) => {
    e.preventDefault();
    const { name, value } = e.target;

    setState({ ...state, [name]: value });
};

請記住,當組件第一次渲染時, useEffect鈎子也會運行。 之后,它只會在state object 更改時運行。

編輯:

If you don' want to make the HTTP request when useEffect runs on initial render of the component, add an if statement inside the useEffect hook's callback that will make sure that HTTP request is only made once you have required data in the state object to make HTTP 請求

useEffect(() => {

    if (state.githubID) {
        API.getsync(state.githubID, state.firstName, state.lastName, state.email);
    }

}, [state]);

Yousaf 讓我走上了正軌,但是,需要修改代碼才能正常工作。 這個問題是通過執行 'API.getsync(state.githubID, state.firstName, state.lastName, state.email);' 在初始加載時,數據庫正在接收數據,該數據告訴應用程序來自 github 的用戶信息在那里,並且從未呈現輸入用戶名的表單。 顯然,如果用戶名未定義,github api 將響應有效但不正確的信息。 api 通過以下方式命中:

axios
.get(
  "https://api.github.com/users/" + developerLoginName + "/repos?type=all"

這導致將用戶“null”的 4 個存儲庫的信息添加到數據庫中!

這已通過從 useEffect 中刪除調用 getsync function 的行來解決。

但是,我發現根本不需要 useEffect 。 只需將擴展運算符添加到“setState”即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM