React 状态不会立即使用 useState 更新



如果你觉得这是一个重复的问题,我很抱歉,但是我在任何类似的问题中都找不到我的问题的解决方案,也不明白为什么会出现这个问题。

我有一个名为Selector.tsx的组件,它基本上有一个输入字段和一堆按钮,当点击这些按钮时,应该用输入字段的数据创建一张卡片。

selector.tsx:


const profileList: Profile[] = [
{
name: 'Website',
value: 'website',
},
{
name: 'Documentation',
value: 'documentation',
},
{
name: 'Telegram',
value: 'telegram',
},
{
name: 'Twitter',
value: 'twitter',
},
{
name: 'Github',
value: 'github',
},
{
name: 'Facebook',
value: 'facebook',
},
{
name: 'Blog',
value: 'blog',
},
{
name: 'Discord',
value: 'discord',
},
{
name: 'LinkedIn',
value: 'linkedin',
},
{
name: 'Slack',
value: 'slack',
},
];
export const Selector: FC<SelectorProps> = ({ wrapperClass }) => {
const [inputVal, setInputVal] = useState('https://google.com');
const [saved, setSaved] = useState<Saved[]>([]);
const handleAdd = (val: string) => {
if (!inputVal) return;
const _saved = saved;
_saved.push({ type: val, text: inputVal });
setSaved(_saved);
};
const handleClearSaved = () => {
setSaved([]);
};
const DisplayCard: FC<DisplayCardProps> = ({ text, type }) => (
<div className="w-full text-left text-text-gray bg-red-100 px-4 py-1 border rounded-lg">
<span className="text-gray-600 text-xs">{type}:</span>
<span className="text-base text-black text-sm ml-4">{text}</span>
</div>
);
return (
<div className="mt-4 py-4 flex flex-col lg:flex-row-reverse gap-4 items-center">
<div className="mt-8 space-y-2 overflow-y-auto border border-blue-500 p-4 rounded">
{saved.length ? (
saved.map(({ type, text }, i) => (
<DisplayCard key={i} text={text} type={type} />
))
) : (
<i>Nothing to show</i>
)}
</div>
<div className="border rounded p-4">
<div className="flex items-center gap-2">
<input
className="flex-grow pl-2 text-sm leading-6 border border-transparent bg-blue-100 rounded outline-none focus:border-prim-border"
value={inputVal}
onChange={(e) => setInputVal(e.target.value)}
/>
<div className="mt-2 flex flex-col space-y-2">
{profileList.map(({ name, value }, i) => (
<button
className="border border-red-400 text-sm bg-black bg-opacity-0 hover:bg-opacity-10 transform scale-100 active:scale-90 disabled:cursor-not-allowed"
onClick={() => handleAdd(value)}
disabled={!inputVal}
>
{name}
</button>
))}
</div>
</div>
<button
className="mt-2 border border-red-500 transform scale-100 active:scale-90 px-2"
onClick={handleClearSaved}
>
Clear Fields
</button>
</div>
</div>
);
};

每当我们点击任何配置文件按钮(和输入字段不是空的),handleSave按钮被称为&saved数组状态应该得到更新(对象被推入数组) &基于此,DisplayCards被渲染。

问题:单击任何配置文件按钮后,saved状态都不会更新。当我们修改输入字段时(这会更新inputVal状态),只有这样saved状态才会更新

同样奇怪的是,当点击清除按钮时,handleClearSaved函数正常工作。可以清空saved数组。但是由于某些原因,压入saved数组似乎并没有更新状态.

Stackblitz中出现的问题:https://stackblitz.com/edit/well-well-well?file=components/Selector.tsx

我不明白为什么这种行为会在反应中发生。我以前从未遇到过这样的问题。如果有人可以帮助或提供任何提示,这将是非常有帮助的。🙏

谢谢。

的原因是你正在做变量(对象)复制与引用,当引用没有改变你的状态不更新

本月的
const handleAdd = (val: string) => {
if (!inputVal) return;
const _saved = saved;
_saved.push({ type: val, text: inputVal });
setSaved(_saved);
};

试试这个代码

const handleAdd = (val: string) => {
if (!inputVal) return;
setSaved((pre) => ([...pre, { type: val, text: inputVal });
};

对象和数组是通过引用来处理的,这意味着你不能像这样复制它们

const a = [1,2,3]
const b = a

复制一个数组,你应该使用ES6的Spread语法来创建一个新的实例,像这样

const a = [1,2,3]
cosnt b = [...a]

react state检查前一个值和下一个值,然后进行更新当引用没有改变时,不发生渲染。为了更新对象状态或数组状态,你应该创建一个新的实例,你可以使用ES6扩展语法

使用此命令直接更改状态:

const handleAdd = (val: string) => {
if (!inputVal) return;
setSaved(prevState => [...prevState, {type: val, text: inputVal}]);
};

此外,你应该添加一个key按钮映射,它会给你一个控制台错误。

最新更新