在单击按钮时反应添加和删除组件
React add and remove a component on button click
我是 React 新手。在这里,我试图在单击 +/- 按钮时 add/remove 一个 'Timer' 组件。单击“+”时效果很好,但单击“-”时效果不佳。我认为每次设置状态时,组件都会重新呈现。但是这里它不会在单击“-”按钮时呈现。
- 这里可能出了什么问题?
- 也欢迎任何更好的方法来做同样的事情。
function App() {
var [timers, setTimers] = useState([]);
var [count, setCount] = useState(0);
const addTimer = () => {
setCount(count + 1);
timers.push(count);
setTimers(timers);
console.log(timers); //[0]
};
const removeTimer = () => {
timers.pop();
setTimers(timers);
console.log(timers); //[]
};
return (
<div>
<button className="button" onClick={addTimer}>
+
</button>
<button className="button" onClick={removeTimer}>
-
</button>
<div>
{timers.map((t) => (
<Timer key={t} />
))}
</div>
</div>
);
}
问题在于,只有在状态发生变化时,React 才会重新渲染。它通过进行 浅比较来检查该事实。 因此,对于对象(或数组,如您的情况),即使您正在更改对象的内容,对象 reference 保持不变。因为 timers.pop()
不会创建新数组。它修改当前数组。
React 会做类似的事情:old array === new array ?
并且会返回 true
,因为它是相同的 array/object 引用。
PS:您的 (+) 按钮之所以起作用,是因为您也在做 setCount(count+1)
。顺便说一下,您应该将其更改为 setCount((prevState) => prevState + 1);
当您的新状态取决于您的上一个状态时,我建议您始终使用这种形式的 setState
调用:
setState((prevState) => {
// READ AND USE OLD prevState
// RETURN BRAND NEW newState
});
你可以这样做:
const addTimer = () => {
setCount((prevState) => prevState + 1);
setTimers((prevState) => {
const newTimers = Array.from(prevState); // CREATING A NEW ARRAY OBJECT
timers.push(count);
return newTimers;
});
};
const removeTimer = () => {
setTimers((prevState) => {
const newTimers = Array.from(prevState); // CREATING A NEW ARRAY OBJECT
newTimers.pop();
return newTimers;
});
};
您正在改变不会触发渲染的状态,请参阅 React 文档中的 Power Of Not Mutating Data。
重写为不可变逻辑可以是:
const addTimer = () => {
setCount((prevCount ) => prevCount + 1);
setTimers((prevTimers) => [...prevTimers, count]);
};
const removeTimer = () => {
setTimers((prevTimers) => prevTimers.slice(0, prevTimers.length - 1));
};
因为您正试图改变状态。这里(在 React 中)有一个不改变状态的原则。所以你不应该 pop 而是在 remove 函数中做类似的事情。它可以帮助您避免任何副作用:
setTimers(state => state.filter((timer, index) => index !== state.length - 1))
它不起作用的原因可能是您 add/remove 使用 push/pop 方法的错误方式。
如果您希望组件重新呈现,则需要使用解构来更改状态。
可能不是最佳解决方案,但应该可行:
const addTimer = () => {
setCount(count + 1)
setTimers([...timers, count])
}
const removeTimer = () => {
let filteredTimers = timers.filter((timer, index) => index !== (timers.length-1))
setTimers([...filteredTimers])
}
我是 React 新手。在这里,我试图在单击 +/- 按钮时 add/remove 一个 'Timer' 组件。单击“+”时效果很好,但单击“-”时效果不佳。我认为每次设置状态时,组件都会重新呈现。但是这里它不会在单击“-”按钮时呈现。
- 这里可能出了什么问题?
- 也欢迎任何更好的方法来做同样的事情。
function App() {
var [timers, setTimers] = useState([]);
var [count, setCount] = useState(0);
const addTimer = () => {
setCount(count + 1);
timers.push(count);
setTimers(timers);
console.log(timers); //[0]
};
const removeTimer = () => {
timers.pop();
setTimers(timers);
console.log(timers); //[]
};
return (
<div>
<button className="button" onClick={addTimer}>
+
</button>
<button className="button" onClick={removeTimer}>
-
</button>
<div>
{timers.map((t) => (
<Timer key={t} />
))}
</div>
</div>
);
}
问题在于,只有在状态发生变化时,React 才会重新渲染。它通过进行 浅比较来检查该事实。 因此,对于对象(或数组,如您的情况),即使您正在更改对象的内容,对象 reference 保持不变。因为 timers.pop()
不会创建新数组。它修改当前数组。
React 会做类似的事情:old array === new array ?
并且会返回 true
,因为它是相同的 array/object 引用。
PS:您的 (+) 按钮之所以起作用,是因为您也在做 setCount(count+1)
。顺便说一下,您应该将其更改为 setCount((prevState) => prevState + 1);
当您的新状态取决于您的上一个状态时,我建议您始终使用这种形式的 setState
调用:
setState((prevState) => {
// READ AND USE OLD prevState
// RETURN BRAND NEW newState
});
你可以这样做:
const addTimer = () => {
setCount((prevState) => prevState + 1);
setTimers((prevState) => {
const newTimers = Array.from(prevState); // CREATING A NEW ARRAY OBJECT
timers.push(count);
return newTimers;
});
};
const removeTimer = () => {
setTimers((prevState) => {
const newTimers = Array.from(prevState); // CREATING A NEW ARRAY OBJECT
newTimers.pop();
return newTimers;
});
};
您正在改变不会触发渲染的状态,请参阅 React 文档中的 Power Of Not Mutating Data。
重写为不可变逻辑可以是:
const addTimer = () => {
setCount((prevCount ) => prevCount + 1);
setTimers((prevTimers) => [...prevTimers, count]);
};
const removeTimer = () => {
setTimers((prevTimers) => prevTimers.slice(0, prevTimers.length - 1));
};
因为您正试图改变状态。这里(在 React 中)有一个不改变状态的原则。所以你不应该 pop 而是在 remove 函数中做类似的事情。它可以帮助您避免任何副作用:
setTimers(state => state.filter((timer, index) => index !== state.length - 1))
它不起作用的原因可能是您 add/remove 使用 push/pop 方法的错误方式。
如果您希望组件重新呈现,则需要使用解构来更改状态。
可能不是最佳解决方案,但应该可行:
const addTimer = () => {
setCount(count + 1)
setTimers([...timers, count])
}
const removeTimer = () => {
let filteredTimers = timers.filter((timer, index) => index !== (timers.length-1))
setTimers([...filteredTimers])
}