点击后反应状态不改变

发布于 2025-01-16 13:29:39 字数 2427 浏览 0 评论 0原文

我正在学习反应。 我的代码应该做什么:它应该根据相应行中的星星值来渲染方块。线条具有从 1 到 5 的数字,方块具有从 1 到 5 的星号。如果方块的星号值为 3,则它应该以相同的数字渲染。 如果更改星星值,方块应在不同的行中渲染。

下面是我的代码。

import react from "react";
import { useState } from "react";

const squares = [
    {'id': 1, 'stars': '5'},
    {'id': 2, 'stars': '4'},
    {'id': 3, 'stars': '3'},
    {'id': 4, 'stars': '3'},
    {'id': 5, 'stars': '5'},
    {'id': 6, 'stars': '4'},
    {'id': 7, 'stars': '2'},
    {'id': 8, 'stars': '1'}
]

const lines = [
    {'id': 1, 'numberName':'One','number': 1},
    {'id': 2, 'numberName':'One','number': 2},
    {'id': 3, 'numberName':'One','number': 3},
    {'id': 4, 'numberName':'One','number': 4},
    {'id': 5, 'numberName':'One','number': 5}
]


function Lines() {
    return (
        lines.map(line => <Line {...line} key={line.id}/>)
    )
}


function Line(props) {
    const [squaresArray, setSquaresArray] = useState(squares)
    function changeSquares(squareId, valueForChange) {
        let oldSquares = squaresArray
        let squareToChange = oldSquares.find(square => square.id == squareId)
        squareToChange.stars = valueForChange
        setSquaresArray(oldSquares)
        console.log(squareId, valueForChange)
    }

    return(
        <div style={{'display':'flex', 'border':'3px red solid', 'padding': '10px'}}>
            {
                squaresArray
                    .filter(square => square.stars == props.number)
                    .map(square => 
                    <Square {...square} changeSquares={changeSquares} squareId={square.id} key={square.id}/>
                )
            }
        </div>  
    )
}

function Square(props) {
    const [stars, setStars] = useState(props.stars)
    return (
        <div style={{'width': '100px','height': '100px','border': 'solid 2px blue','margin-right': '5px'}}>
                <input type='number' name='numb' value={stars} style={{'width':'25px'}} onChange={(e) => {setStars(e.target.value)}}></input>
                <button onClick={() => {props.changeSquares(props.squareId,stars)}} >Save</button>
        </div>
    )
}

function App() {  
    return (
        <Lines lines={lines}/>
    )
}

export default App;

第 61 行有 onClick 函数。该函数应该更改页面的状态并根据新的平方值重新渲染我的应用程序。但唯一发生的事情是第 40 行的 console.log。我可以看到在第 39 行变量 oldSquares 在单击按钮后正确传递了更新的星值,但方块没有重新渲染。

请帮忙。

I am learning react.
What my code should do: It should render the squares based on their stars value in corresponding line. Lines have numbers through 1 to 5, and squares have stars trhough 1 to 5. If the square has stars value of 3, then it should render in line with the same number.
If you change the stars value, square should render in different line.

Below is my code.

import react from "react";
import { useState } from "react";

const squares = [
    {'id': 1, 'stars': '5'},
    {'id': 2, 'stars': '4'},
    {'id': 3, 'stars': '3'},
    {'id': 4, 'stars': '3'},
    {'id': 5, 'stars': '5'},
    {'id': 6, 'stars': '4'},
    {'id': 7, 'stars': '2'},
    {'id': 8, 'stars': '1'}
]

const lines = [
    {'id': 1, 'numberName':'One','number': 1},
    {'id': 2, 'numberName':'One','number': 2},
    {'id': 3, 'numberName':'One','number': 3},
    {'id': 4, 'numberName':'One','number': 4},
    {'id': 5, 'numberName':'One','number': 5}
]


function Lines() {
    return (
        lines.map(line => <Line {...line} key={line.id}/>)
    )
}


function Line(props) {
    const [squaresArray, setSquaresArray] = useState(squares)
    function changeSquares(squareId, valueForChange) {
        let oldSquares = squaresArray
        let squareToChange = oldSquares.find(square => square.id == squareId)
        squareToChange.stars = valueForChange
        setSquaresArray(oldSquares)
        console.log(squareId, valueForChange)
    }

    return(
        <div style={{'display':'flex', 'border':'3px red solid', 'padding': '10px'}}>
            {
                squaresArray
                    .filter(square => square.stars == props.number)
                    .map(square => 
                    <Square {...square} changeSquares={changeSquares} squareId={square.id} key={square.id}/>
                )
            }
        </div>  
    )
}

function Square(props) {
    const [stars, setStars] = useState(props.stars)
    return (
        <div style={{'width': '100px','height': '100px','border': 'solid 2px blue','margin-right': '5px'}}>
                <input type='number' name='numb' value={stars} style={{'width':'25px'}} onChange={(e) => {setStars(e.target.value)}}></input>
                <button onClick={() => {props.changeSquares(props.squareId,stars)}} >Save</button>
        </div>
    )
}

function App() {  
    return (
        <Lines lines={lines}/>
    )
}

export default App;

There is onClick function on line 61. This function should change the state of page and rerender my app based on new square values. But only thing that happens is the console.log on line 40. And I can see that on line 39 variable oldSquares is passed correctly with updated star value after clicking button, but the squares are NOT rerendering.

Please help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ぇ气 2025-01-23 13:29:39

状态在 changeSquares 处理程序中发生变化,并且数组引用永远不会更新。

function changeSquares(squareId, valueForChange) {
  let oldSquares = squaresArray // <-- reference to state
  let squareToChange = oldSquares.find(square => square.id == squareId)
  squareToChange.stars = valueForChange // <-- mutation!!
  setSquaresArray(oldSquares) // <-- same reference saved back into state
  console.log(squareId, valueForChange)
}

使用功能状态更新从先前的状态进行更新,并将数组的浅表副本创建到新的数组引用中。

function changeSquares(squareId, valueForChange) {
  setSquaresArray(squares => squares.map(square => square.id == squareId
    ? {
      ...square,
      stars: valueForChange
    }
    : square
  ));
  console.log(squareId, valueForChange)
}

The state is mutated in the changeSquares handler and the array reference is never updated.

function changeSquares(squareId, valueForChange) {
  let oldSquares = squaresArray // <-- reference to state
  let squareToChange = oldSquares.find(square => square.id == squareId)
  squareToChange.stars = valueForChange // <-- mutation!!
  setSquaresArray(oldSquares) // <-- same reference saved back into state
  console.log(squareId, valueForChange)
}

Use a functional state update to update from the previous state and create a shallow copy of the array into a new array reference.

function changeSquares(squareId, valueForChange) {
  setSquaresArray(squares => squares.map(square => square.id == squareId
    ? {
      ...square,
      stars: valueForChange
    }
    : square
  ));
  console.log(squareId, valueForChange)
}
只有一腔孤勇 2025-01-23 13:29:39

这是 @drew-reese 建议的更改后的解决方案

import react from "react";
import { useState } from "react";

const squares = [
    {'id': 1, 'stars': '5'},
    {'id': 2, 'stars': '4'},
    {'id': 3, 'stars': '3'},
    {'id': 4, 'stars': '3'},
    {'id': 5, 'stars': '5'},
    {'id': 6, 'stars': '4'},
    {'id': 7, 'stars': '2'},
    {'id': 8, 'stars': '1'}
]

const lines = [
    {'id': 1, 'numberName':'One','number': 1},
    {'id': 2, 'numberName':'One','number': 2},
    {'id': 3, 'numberName':'One','number': 3},
    {'id': 4, 'numberName':'One','number': 4},
    {'id': 5, 'numberName':'One','number': 5}
]


function Lines(props) {
    const [squaresArray, setSquaresArray] = useState(squares)
    function changeSquares(squareId, valueForChange) {
        setSquaresArray(squares => squares.map(square => square.id == squareId
            ? {
              ...square,
              stars: valueForChange
            }
            : square
          ))
    }
    return (
        props.lines.map(line => <Line {...line} key={line.id} squaresArray={squaresArray} changeSquares={changeSquares}/>)
    )
}


function Line(props) {


    return(
        <div style={{'display':'flex', 'border':'3px red solid', 'padding': '10px'}}>
            {
                props.squaresArray
                    .filter(square => square.stars == props.number)
                    .map(square => 
                    <Square {...square} changeSquares={props.changeSquares} squareId={square.id} key={square.id}/>
                )
            }
        </div>  
    )
}

function Square(props) {
    const [stars, setStars] = useState(props.stars)
    return (
        <div style={{'width': '100px','height': '100px','border': 'solid 2px blue','marginRight': '5px'}}>
                <input type='number' name='numb' value={stars} style={{'width':'25px'}} onChange={(e) => {setStars(e.target.value)}}></input>
                <button onClick={() => {props.changeSquares(props.squareId,stars)}} >Save</button>
        </div>
    )
}

function App() {  
    return (
        <Lines lines={lines}/>
    )
}

export default App;

Here is the soulution after changes sugested by @drew-reese

import react from "react";
import { useState } from "react";

const squares = [
    {'id': 1, 'stars': '5'},
    {'id': 2, 'stars': '4'},
    {'id': 3, 'stars': '3'},
    {'id': 4, 'stars': '3'},
    {'id': 5, 'stars': '5'},
    {'id': 6, 'stars': '4'},
    {'id': 7, 'stars': '2'},
    {'id': 8, 'stars': '1'}
]

const lines = [
    {'id': 1, 'numberName':'One','number': 1},
    {'id': 2, 'numberName':'One','number': 2},
    {'id': 3, 'numberName':'One','number': 3},
    {'id': 4, 'numberName':'One','number': 4},
    {'id': 5, 'numberName':'One','number': 5}
]


function Lines(props) {
    const [squaresArray, setSquaresArray] = useState(squares)
    function changeSquares(squareId, valueForChange) {
        setSquaresArray(squares => squares.map(square => square.id == squareId
            ? {
              ...square,
              stars: valueForChange
            }
            : square
          ))
    }
    return (
        props.lines.map(line => <Line {...line} key={line.id} squaresArray={squaresArray} changeSquares={changeSquares}/>)
    )
}


function Line(props) {


    return(
        <div style={{'display':'flex', 'border':'3px red solid', 'padding': '10px'}}>
            {
                props.squaresArray
                    .filter(square => square.stars == props.number)
                    .map(square => 
                    <Square {...square} changeSquares={props.changeSquares} squareId={square.id} key={square.id}/>
                )
            }
        </div>  
    )
}

function Square(props) {
    const [stars, setStars] = useState(props.stars)
    return (
        <div style={{'width': '100px','height': '100px','border': 'solid 2px blue','marginRight': '5px'}}>
                <input type='number' name='numb' value={stars} style={{'width':'25px'}} onChange={(e) => {setStars(e.target.value)}}></input>
                <button onClick={() => {props.changeSquares(props.squareId,stars)}} >Save</button>
        </div>
    )
}

function App() {  
    return (
        <Lines lines={lines}/>
    )
}

export default App;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文