[英]React component not rerendering after state change, but render() is being called
[英]react not rerendering after state change
我知道有类似的问题,但我有一个奇怪的问题。
这就是我正在做的
import React, {useState} from 'react';
import './App.css';
import {Table, Button, InputGroup, FormControl} from 'react-bootstrap';
function App() {
const [pons, setPons] = useState();
const [translations, setTranslations] = useState([]);
const [isInEditMode, setIsInEditMode] = useState(false);
const [inputValue, setInputValue] = useState('samochod');
const [errors, setErrors] = useState([]);
const [translationsToSave, setTranslationsToSave] = useState([]);
const changeIsInEditMode = () => setIsInEditMode(!isInEditMode);
const handleEditButtonClick = (id) => console.log('Edit', id);
const handleDeleteButtonClick = (id) => console.log('Delete', id);
const handleInputChange = (e) => setInputValue(e.target.value);
const handleFetchOnButtonClick = async () => {
const resp = await fetch(`http://localhost:8080/pons/findTranslation/${inputValue}`).then(r => r.json()).catch(e => console.log(e));
if (resp.ok === true) {
setTranslations(resp.resp[0].hits);
setErrors([]);
} else {
setErrors(resp.errors ? resp.errors : ['Something went wrong. check the input']);
}
};
const handleSaveTranslations = async () => {
const resp = await fetch('localhost:8080/pons/', {method: 'POST', body: {content: translationsToSave}});
if (resp.ok === true) {
setInputValue('');
setTranslations(null);
}
};
return (
<div className="App">
{errors.length > 0 ? errors.map(e => <div key={e}>{e}</div>) : null}
<InputGroup className="mb-3">
<FormControl
value={inputValue}
onChange={handleInputChange}
placeholder={inputValue}
/>
</InputGroup>
<div className="mb-3">
<Button onClick={handleFetchOnButtonClick} disabled={inputValue === '' || errors.length > 0}>Translate</Button>
<Button onClick={changeIsInEditMode}>
{isInEditMode ? 'Exit edit mode' : 'Enter edit mode'}
</Button>
<Button disabled={translationsToSave.length === 0} onClick={handleSaveTranslations}>Save translations</Button>
</div>
<Table striped bordered hover>
<thead>
<tr>
<th>Original</th>
<th>Translation</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{translations ? translations.map(pon => pon.roms.map(rom => rom.arabs.map(arab => arab.translations.map(translation => {
const {source, target} = translation;
return (
<tr>
<td><span dangerouslySetInnerHTML={{__html: source}}/></td>
<td><span dangerouslySetInnerHTML={{__html: target}}/></td>
<td>
{
!translationsToSave.includes(target) ?
<Button onClick={() => {
const tmp = translationsToSave;
tmp.push(target);
setTranslationsToSave(tmp);
}}>
Add translation
</Button>
:
<Button
onClick={() => {
const tmp = translationsToSave;
tmp.splice(tmp.findIndex(elem => elem === target));
setTranslationsToSave(tmp);
}}>
Remove translation
</Button>
}
</td>
</tr>
)
})))) : (
<div>No translations</div>
)}
</tbody>
</Table>
</div>
);
}
export default App;
所以它是一个基本的应用程序,它现在只是在数组中添加和删除setTranslationsToSave
。 单击“ Add translation
”按钮后,视图保持不变。 但是当我单击Enter edit mode
时它会刷新。 与Remove translation
相同。 我需要点击Enter/Exit edit mode
。
点击Translate
也会重新加载视图。 所以Add/Remove translation
按钮是唯一不刷新页面的按钮。 为什么? 我错过了什么?
问题是您正在更改添加/删除翻译按钮中的 satte,因此在重新渲染之前进行反应检查时,如果使用相同的 state 调用 state 更新程序,它会感觉没有任何变化,因为它进行了参考检查,因此没有t 触发重新渲染
此外,在基于以前的 state 更新当前 state 时, functional callback approach for state updater
。
如下更新您的 state
<Button onClick={() => {
setTranslationsToSave(prev => [...prev, target]);
}}>
Add translation
</Button>
:
<Button
onClick={() => {
setTranslationsToSave((prev) => {
const index = prev.findIndex(elem => elem === target)); return [...prev.slice(0, index), ...prev.slice(index + 1)]
});
}}>
Remove translation
</Button>
在您的Add translation
点击处理程序中,您正在改变 state:
<Button onClick={() => {
// tmp is just a reference to state
const tmp = translationsToSave;
// You are mutating state, this will be lost
tmp.push(target);
setTranslationsToSave(tmp);
}}>
您应该复制 state 并添加新元素:
<Button onClick={() => {
setTranslationsToSave([...translationsToSave, target]);
}}>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.