LocalStorage 不使用 React 钩子更新状态中的属性

麦克莫尔

我正在尝试更新先前在 useState 挂钩中为表单值声明的对象属性,并将其保存在 localstorage 中。一切顺利,但 localstorage 一直将日期属性保存为空,我知道这一定是因为异步,但我找不到解决方案。这是我的代码。我是 React 钩子的新手。非常感谢!

  const [formValues,setformValues] = useState(
    {
      userName:'',
      tweetText:'',
      date:''
    }
  )

  const getlocalValue = () => {
    const localValue = JSON.parse(localStorage.getItem('tweetList'));
    if(localValue !== null){
      return localValue
    } else {
      return []
    }
  }

  const [tweetList,setTweetList] = useState(getlocalValue());

  const handleInput = (inputName,inputValue) => {
    setformValues((prevFormValues) => {
      return {
        ...prevFormValues,
        [inputName]:inputValue
      }
    })
  }

  const handleForm = () => {
    const {userName,tweetText} = formValues;
    if(!userName || !tweetText) {
      console.log('your tweet is empty');
    } else {
      setformValues(prevFormValues => {
        return {
          ...prevFormValues,
          date:getCurrentDate() //this is not updating in local
        }
      })
      setTweetList(prevTweets => ([...prevTweets, formValues]));
      toggleHidden(!isOpen)
    }

  }
  console.log(formValues) //but you can see changes outside the function


  useEffect(() => {
    localStorage.setItem('tweetList', JSON.stringify(tweetList));
  }, [tweetList]);

扎卡里·哈伯

在这种情况下,问题是因为被调用的 handleForm 仍然只能访问调用它时的 formValues 状态,而不是新状态。因此,处理此问题的最简单方法是根据更新后的 formValues 的本地副本更新 formValues、setFormValues 和 setTweetList。

  const handleForm = () => {
    const {userName,tweetText} = formValues;
    if(!userName || !tweetText) {
      console.log('your tweet is empty');
    } else {
      const updatedFormValues = {...formValues,date:getCurrentDate()};
      setformValues(updatedFormValues)
      setTweetList(prevTweets => ([...prevTweets, updatedFormValues]));
      toggleHidden(!isOpen)
    }
  }

由于这里存在并发问题:即您不能保证使用最新数据更新 formValues 和 tweetList 的状态。另一种选择是 useReducer 而不是两个单独的状态变量,因为它们是相关的属性,您可以更轻松地相互更新它们。

作为使用 reducer 进行更复杂更新的示例,我添加了一个 'FINALIZE_TWEET' 操作,该操作将同时执行操作的两个部分。

const Component = () => {
  const [{ formValues, tweetList }, dispatch] = useReducer(
    reducer,
    undefined,
    getInitState
  );

  const handleInput = (inputName, inputValue) => {
    dispatch({ type: 'SET_FORM_VALUE', payload: { inputName, inputValue } });
  };

  const handleForm = () => {
    const { userName, tweetText } = formValues;
    if (!userName || !tweetText) {
      console.log('your tweet is empty');
    } else {
      dispatch({ type: 'SET_FORM_DATE' });
      dispatch({ type: 'PUSH_TO_LIST' });
      // OR
      // dispatch({type: 'FINALIZE_TWEET'})
      toggleHidden(!isOpen);
    }
  };
  console.log(formValues); //but you can see changes outside the function

  useEffect(() => {
    localStorage.setItem('tweetList', JSON.stringify(tweetList));
  }, [tweetList]);

  return <div></div>;
};

const getlocalValue = () => {
  const localValue = JSON.parse(localStorage.getItem('tweetList'));
  if (localValue !== null) {
    return localValue;
  } else {
    return [];
  }
};
function getInitState() {
  const initialState = {
    formValues: {
      userName: '',
      tweetText: '',
      date: '',
    },
    tweetList: getlocalValue(),
  };
}

function reducer(state, action) {
  switch (action.type) {
    case 'SET_FORM_VALUE':
      return {
        ...state,
        formValues: {
          ...state.formValues,
          [action.payload.inputName]: action.payload.inputValue,
        },
      };
    case 'SET_FORM_DATE':
      return {
        ...state,
        formValues: {
          ...state.formValues,
          date: getCurrentDate(),
        },
      };
    case 'PUSH_TO_LIST':
      return {
        ...state,
        tweetList: [...state.tweetList, state.formValues],
      };
    case 'FINALIZE_TWEET': {
      const newTweet = {
        ...state.formValues,
        date: getCurrentDate(),
      };
      return {
        ...state,
        formValues: newTweet,
        tweetList: [...state.tweetList, newTweet],
      };
    }
    default:
      return state;
  }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用 React 钩子在 localStorage 中存储初始切换状态

在react.js中如何使用localStorage?

在React中使用localStorage

React中的LocalStorage问题

React 中的 LocalStorage 模式

react 不会根据状态更新 localstorage 值

无法使用钩子在 React 中设置状态

在 React 中使用钩子更新状态时,如何从数组中的对象中提取数据?

ReactJS:如何使用localStorage更新属性状态?

在React中使用LocalStorage吗?

使用React钩子更新动态状态的方式是什么?

使用React useState()钩子更新和合并状态对象

React钩子:如何使用useState()更新嵌套对象上的状态?

可以在不使用钩子的无状态React组件中使用lodash防反跳吗?

在类组件中的React,React中使用recoil.js而不使用钩子

如何在React中使用钩子从父组件获取其值的父组件中更新正确的状态值?

setTimeout中调用的函数不使用当前的React状态

如何使用React钩子以当前状态和先前状态更新当前状态

Firefox中的onmozfullscreenchange警告(不使用react)

尝试使用钩子在 react redux 中检索存储状态

Angular组件视图层不使用localStorage更改而无需更新而不进行刷新

如何使用 React 从 localStorage 读取多个键?

使用localStorage令牌登录React.js

如何使用 React Hooks 添加 cookie 或 localstorage

React,使用 localStorage 实现暗光模式

在localStorage中添加字符串数组,但不使用转义字符

如何不使用localStorage进行重构?

在不使用React.createClass的情况下使用props在react中播种初始状态

React JavaScript中的LocalStorage解构数据