【问题标题】:React State Hook - I can't set stateReact State Hook - 我无法设置状态
【发布时间】:2020-08-23 06:59:56
【问题描述】:

我正在尝试在我的 React 应用中实现 Facebook 登录。

const [formData, setFormData] = useState({
    name: "",
    surname: "",
    email: "",
    password: "",
  });

Facebook 在这里登录

<FacebookLogin
 appId=""
 autoLoad={true}
 fields="first_name,last_name,email,id"
 onClick={(e) => componentClicked(e)}
 callback={(response) => responseFacebook(response)}
 textButton={msg}
 cssClass="btn btn-primary btn-sm"
 icon="fa-facebook"
 />

数据来了:

const responseFacebook = (response) => {
    setFormData({ ...formData, name: response.first_name });
    setFormData({ ...formData, surname: response.last_name });
    setFormData({ ...formData, email: response.email });
    setFormData({ ...formData, password: response.id });
    console.log(formData.name);
    console.log(formData.surname);
    /* register({ name, surname, email, password }); */
  };

我无法设置 formData.x。 response.first_name 或其他人正在使用 console.log,但是当我尝试设置状态时,它什么也没有。

例如,console.log(formData.name) 什么也不返回。

【问题讨论】:

标签: javascript reactjs react-hooks


【解决方案1】:
setFormData({ ...formData, name: response.first_name });
setFormData({ ...formData, surname: response.last_name });
setFormData({ ...formData, email: response.email });
setFormData({ ...formData, password: response.id });

问题是formData 在下一次渲染之前不会改变。 formData 的值是上一次渲染的值,并且在下一次渲染之前一直保持这种状态。因此,上述每一行都设置了旧数据,加上一个更改的属性。然后下一行将旧数据设置为具有不同的更改属性,并且您之前更改的属性将丢失。

您只需调用一次setFormData,即可进行所有您想要的更改。这样你就不需要formData 来更新,直到你完成所有设置。

setFormData({
  ...formData,
  name: response.first_name,
  surname: response.last_name,
  email: response.email,
  password: response.id,
});

但是在这里查看您的状态结构,您根本不需要以前的值,因为每个键都在响应中:

setFormData({
  name: response.first_name,
  surname: response.last_name,
  email: response.email,
  password: response.id,
});

【讨论】:

  • 这是一种不好的做法。在将数据合并到状态时,我们将使用 setState 回调。否则,您的状态可能会过时。
  • @IanVasco 您并不总是需要使用回调。这是一个有用的工具,但它取决于数据在应用程序中的流动方式。但是,在这种情况下,甚至根本不需要先前的状态。
  • 我同意这个特定用例不需要。但是,我认为这是减少副作用的好习惯
【解决方案2】:

你应该使用之前的状态或者只调用一次setFormData

// using previous state
// this solves your problem but isn't that good
// because you don't need to call it many times
const responseFacebook = (response) => {
    setFormData(prev => ({ ...prev, name: response.first_name });
    setFormData(prev => ({ ...prev, surname: response.last_name });
    setFormData(prev => ({ ...prev, email: response.email });
    setFormData(prev => ({ ...prev, password: response.id });
};

// calling only once
const responseFacebook = (response) => {
    setFormData({ 
         name: response.first_name,
         surname: response.last_name,
         email: response.email,
         password: response.id 
    });
};

【讨论】:

    【解决方案3】:

    使用 usestate 设置状态和 useeffect 挂钩到控制台更改, 你的状态不会改变,因为它是一个异步任务,在钩子中没有像类一样设置状态的回调函数,所以使用 useEffect

    const responseFacebook = (response) => {
        setFormData({ 
          ...formData, 
          name: response.first_name 
          surname: response.last_name,
          email: response.email,
          password: response.id 
        });
    });
    
    useEffect(() => {
       console.log(formData.name);
        console.log(formData.surname);
    }, [formData]);
    

    【讨论】:

      【解决方案4】:

      useState Hooks 是异步的,您将无法立即看到反映的数据,而是使用 useEffect 来查看您的结果

      const responseFacebook = (response) => {
          setFormData({ ...formData, name: response.first_name });
          setFormData({ ...formData, surname: response.last_name });
          setFormData({ ...formData, email: response.email });
          setFormData({ ...formData, password: response.id });
          console.log(formData.name); // This won't show the results
          console.log(formData.surname); // This won't show the results
          /* register({ name, surname, email, password }); */ // This won't show the results
        };
      
      useEffect(() => {
          // action on update of formData
       console.log(formData);
      }, [formData]);
      

      您还可以进一步优化您的代码:

         setFormData({ 
          ...formData,
          name: response.first_name,
          surname: response.last_name,
          email: response.email,
          password: response.id 
         });
      
      useEffect(() => {
          // action on update of formData
       console.log(formData);
      }, [formData]);
      

      【讨论】:

        猜你喜欢
        • 2020-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-21
        • 2021-11-13
        • 2021-06-03
        • 1970-01-01
        相关资源
        最近更新 更多