React render vs. UseState



我对这个很陌生,不能真正弄清楚渲染是如何工作的-现在坚持使用UseState:) -。因为我看到很多人都在用它,所以我想问一下我做错了什么。这里有2个例子,一个用UseState,工作得很好,另一个用渲染,什么也不做,我添加了一些风格,所以它看起来可以接受任何人尝试。

任何帮助都很感激,谢谢你

//USESTATE

const [newColor, setNewColor] = useState('green');

useEffect(() => {
setBorder()
}, [newColor])

function setBorder() {
if (newColor === 'green') {
document.getElementById('green').style.borderColor = "orange";
document.getElementById('yellow').style.borderColor = "black";
document.getElementById('red').style.borderColor = "black";
}
if (newColor === 'yellow') {
document.getElementById('yellow').style.borderColor = "orange";
document.getElementById('green').style.borderColor = "black";
document.getElementById('red').style.borderColor = "black";
}
if (newColor === 'red') {
document.getElementById('red').style.borderColor = "orange";
document.getElementById('green').style.borderColor = "black";
document.getElementById('yellow').style.borderColor = "black";
}
}

const changeBg = () => {
document.body.style.backgroundColor = newColor;
}

return (
<div>
<div style={{width: '240px', height: '88px', border: '3px solid black', 'borderRadius': '10px'}}>
<div id="green" onClick={(e) => setNewColor(e.target.id)}    style={{width: '40px', height: '40px', background: 'green', border: '3px solid black', float: 'left', margin: '20px 0 0 30px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
<div id="yellow" onClick={(e) => setNewColor(e.target.id)}   style={{width: '40px', height: '40px', background: 'yellow', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
<div id="red" onClick={(e) => setNewColor(e.target.id)}      style={{width: '40px', height: '40px', background: 'red', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
</div>
<button onClick={changeBg}>SAVE</button>
</div>
);

//

渲染
class Test1 extends Component {
constructor(props) {
super(props);
this.state = {
newColor: 'green'
}
}

componentDidUpdate() {
if (this.newColor === 'green') {
document.getElementById('green').style.borderColor = "orange";
document.getElementById('yellow').style.borderColor = "black";
document.getElementById('red').style.borderColor = "black";
}
if (this.newColor === 'yellow') {
document.getElementById('yellow').style.borderColor = "orange";
document.getElementById('green').style.borderColor = "black";
document.getElementById('red').style.borderColor = "black";
}
if (this.newColor === 'red') {
document.getElementById('red').style.borderColor = "orange";
document.getElementById('green').style.borderColor = "black";
document.getElementById('yellow').style.borderColor = "black";
}
}

render() {

const changeBg = () => {
document.body.style.backgroundColor = this.newColor;
}


return (
<div>
<div style={{width: '240px', height: '88px', border: '3px solid black', 'borderRadius': '10px'}}>
<div id="green" onClick={(e) => this.state={newColor: e.target.id}}    style={{width: '40px', height: '40px', background: 'green', border: '3px solid black', float: 'left', margin: '20px 0 0 30px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
<div id="yellow" onClick={(e) => this.state={newColor: e.target.id}}   style={{width: '40px', height: '40px', background: 'yellow', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
<div id="red" onClick={(e) => this.state={newColor: e.target.id}}      style={{width: '40px', height: '40px', background: 'red', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
</div>
<button onClick={changeBg}>SAVE</button>
</div>
);
}
}

首先,永远不要在react中直接*更新DOM。在这两个例子中都是这样做的。第二个例子不工作的原因是,componentDidUpdate在更新发生时被调用(例如状态改变或道具改变),这不会发生,因为你没有在第二个例子中调用setState;而不是直接分配给this.state。而且应该是this.state.newColor,如评论中所述。

在react中解决这个问题的惯用方法是:

export default function App() {
const [newColor, setNewColor] = React.useState('green');
const changeBg = () => {
document.body.style.backgroundColor = newColor;
};
return (
<div>
<div
style={{
width: '240px',
height: '88px',
border: '3px solid black',
borderRadius: '10px',
}}
>
{['green', 'yellow', 'red'].map((x) => (
<div
onClick={(e) => setNewColor(x)}
style={{
width: '40px',
height: '40px',
background: x,
border: '3px solid black',
borderColor: newColor === x ? 'orange' : 'black',
float: 'left',
margin: '20px 0 0 30px',
borderRadius: '10px',
cursor: 'pointer',
}}
></div>
))}
</div>
<button onClick={changeBg}>SAVE</button>
</div>
);
}

虽然这些盒子现在没有很好地居中,因为你在第一个元素有不同的边距,当所有的div是手工写出来的。但是现在所有的边距都是一样的因为我用了一个循环。我把它留给你来调整。


*在极少数情况下你可以,当说与第三方库集成时,但在这种情况下,你应该确保react不触及那部分DOM。

最新更新