【问题标题】:State change not being reflected未反映状态变化
【发布时间】:2021-12-28 11:36:14
【问题描述】:

我是新来的反应。我正在做一个小项目。 我必须显示一个表(listFeatures.js),并且可以通过表单提交(addTech.js)将行添加到表中。但是状态变化并没有得到反映。在这种情况下,我可能觉得 useEffect() 可以帮助我,但我不知道如何正确使用它。有人可以帮忙吗...

下面给出的代码

app.js

import React, { useState, useEffect } from 'react'
import ListFeatures from './components/ListFeatures/listFeatures'
import AddTech from './components/AddTech/addTech'

const App = () => {

  const [resourceType, setResourceType] = useState('posts')

  const [tech, setTech] = useState({
    t_names: ["Java", "Python", "C++"],
    feature: [
      {
        name: "Speed",
        feat_list: [
          {desc: "fast", score: 7},
          {desc: "slow", score: 5},
          {desc: "very fast", score: 9}
        ]
       },
       {
        name: "Complexity",
        feat_list: [
          {desc: "High", score: 3},
          {desc: "Low", score: 8},
          {desc: "Medium", score: 6}
        ]
       },
       {
        name: "Modulartiy",
        feat_list: [
          {desc: "medium", score: 7},
          {desc: "Low", score: 6},
          {desc: "High", score: 9}
        ]
       },
    ],
  }) 
  
  const AddNewTechHandler = (newTech) => {

    const newTable = tech

    newTable.t_names.push(newTech.t_names)
    newTable.feature.map((feat, index) => {
        feat.feat_list.push(newTech.feature[index]) 
    })

    setTech(newTable)
    console.log(tech)
    // This console.log shows tech being updated but the changes are not reflected.
  }   

  return (
    <div className = "container">
      <AddTech onAddTech = {AddNewTechHandler}/>
      <ListFeatures tech = {tech} />
    </div>
  )
}

export default App

listFeatures.js

import React from 'react'

const ListFeatures = (props) => {
    return (
        <table>
            <tr>
                <th></th>
                {
                    props.tech.t_names.map((tech) => {
                        return (
                            <React.Fragment>
                                <th> {tech} </th>
                                <th></th>
                            </React.Fragment>
                        )
                    })
                }
            </tr>
            {
                props.tech.feature.map((techs) => {
                    return(
                        <tbody>
                            <tr>
                                <td>{techs.name}</td>
                                {
                                    techs.feat_list.map((feature) => {
                                        return(
                                            <React.Fragment>
                                                <td>{feature.desc}</td>
                                                <td>{feature.score}</td>
                                            </React.Fragment>
                                        )
                                    })
                                }
                            </tr>
                        </tbody>
                    )
                })    
            }
        </table>
    )
}

export default ListFeatures

addTech.js

import React, { useState } from 'react'

const tech_list = ['Python', 'Java', 'C++', 'JS'];

const AddTech = (props) => {

    const [techChosen, setTechChosen] = useState('')

    const addTechHandler = event => {
        event.preventDefault();
        console.log("Is this working ?")

        console.log(techChosen)

        const newTech = {
            // There will be an api call over here in the future.. for now dummy value.
            t_names: "Js",
            feature: [
                {
                    desc: "fast",
                    score: 8,
                },
                {
                    desc: "High",
                    score: 2
                },
                {
                    desc: "medium",
                    score: 8
                },
            ],
        }

        props.onAddTech(newTech);
    }

    const optionChangeHandler = event => {
        setTechChosen(event.target.value);
    }

    return (
        <div className = "container">
            <form onSubmit={addTechHandler}>
                <label>Choose Tech</label>
                <select name="tech" id="tech" onChange={optionChangeHandler}>
                    <option value="">Select a Tech</option>
                    {
                        tech_list.map((tech) => {
                            return(
                                <option value={tech}>{tech}</option>
                            )
                        })
                    }
                </select>
                <button type="submit">Add Tech</button>
            </form>
        </div>
    );
};

export default AddTech;

【问题讨论】:

标签: javascript reactjs react-hooks


【解决方案1】:

考虑以下两件事并再次尝试您的解决方案:

  1. const newTable = tech 将简单地将tech 的指针引用传递给newTable,两者都指向同一个对象内存。相反,在使用状态变量时尝试创建一个新的对象/数组。尝试对象解构:var newTable = {...tech}。这将创建一个新对象。
  2. 在处理新状态更改依赖于上一个状态的状态时。状态,使用 useState 函数格式,而不是像在 AddNewTechHandler 函数中那样直接更新/改变状态。例如:setTech(oldTech =&gt; { return oldTech.targetKey = 'newValue' });

【讨论】:

  • 谢谢..解决方案有效。实际上有2个问题。首先,我没有考虑指针引用,实际上我忘记了 app.js 中的 tech 实际上是一个对象而不是数组这一事实。我花了很多时间尝试做[...tech] 而不是{...tech}。一开始我没有意识到,但偶然我在浏览器中打开了开发者控制台,然后注意到tech 是不可迭代的。
【解决方案2】:

更新app.js中的状态时需要克隆数组, 代码 const newTable = tech 将简单地通过引用您的数组 fo 对象来传递,而不是您可以执行 const newTable = [...tech] 或在更新状态时通过调用 setTech([...newTable]) 设置状态

 const AddNewTechHandler = (newTech) => {
  const newTable = tech;

  newTable.t_names.push(newTech.t_names);
  newTable.feature.map((feat, index) => {
    feat.feat_list.push(newTech.feature[index]);
  });
  // see how the state is set, setTech(newTable) is practically passing the same array so there is not effect
  setTech([...newTable]);
};

【讨论】:

    猜你喜欢
    • 2021-05-21
    • 2021-09-18
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多