Built React App 运行良好,但开发模式下的同一个 App(npm start)运行不正常

Built React App works fine but same App in Dev mode (npm start) works not properly

我是 React 和制作前端应用程序的初学者,所以我决定学习 this youtube react tutorial。我对 html、js 和 css.

有一些了解

Link 导致我遇到问题的课程(关于 React 中的 state 的练习)。问题是:

onChange 分配给复选框的功能,当通过以下方式启动应用程序时:npm start,正在执行... 奇怪。如果我这样做,相同的功能将按预期工作:npm run buildserve -s build.

在教程中一切正常,我检查了我的代码,它与教程中的代码 100% 相同。我还将我的源代码发送给了我的一位同事并且......一切都像教程中那样工作(我们都安装了 Windows 10)。

当尝试通过 serve -s build 启动应用程序时,我鼓励另一个问题,我在 this question 的帮助下解决了这个问题(脚本的执行在这个系统上被禁用 - 我在 windows powerShell 中 运行 Set-ExecutionPolicy RemoteSigned

我也试过删除 node_modules 和 运行 npm install.

App.js(我删除了App.js的导入和导出):

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      todos: checklist
    }
    this.handleChange = this.handleChange.bind(this)
  } 
  handleChange(id) {
    console.log("debug1", id)
    this.setState(prevState => {
      const updatedToDos = prevState.todos.map(todo => {
        if (todo.id === id) {
          console.log(todo.id, id, todo.isChecked)
          todo.isChecked = !todo.isChecked
          console.log(todo.id, id, todo.isChecked)
        }
        console.log(todo)
        return todo
      })
      console.log(updatedToDos)
      return {
        todos: updatedToDos
      }
    })
  }
  render() {
    const todoChecklist = this.state.todos.map(item => <ToDoItm key={item.id} item={item} 
      handleChange={this.handleChange.bind(this)}/>)
    return(
      <div>
        {todoChecklist}
      </div>
    )
  }
}

checklist.js 是包含 TodoItems

集合的 json 文件

ToDoItm(也删除了导出和导入):

function ToDoItm(props) {
    return (
        <div className="todo-item">
            <h1>{props.item.line}</h1>
            <input 
                type="checkbox" 
                checked={props.item.isChecked}
                onChange={() => props.handleChange(props.item.id)} 
            />
        </div>
    )
}

PS。 表演 奇怪 我的意思是 - 这是当我单击第一个复选框时发生的事情:

所以基本上在这里你正在改变反应状态的原始对象,这不是正确的做法你需要做的是克隆这个待办事项中的那些对象 array.You 可以在下面跟随 code.Also 这个 handleChange 整体没有优化它可以用更有效的方式编写但是对于初学者来说没关系请阅读这个https://daveceddia.com/why-not-modify-react-state-directly/

import React from 'react';

function ToDoItm(props) {
  return (
    <div className="todo-item">
      <h1>{props.item.line}</h1>
      <input
        type="checkbox"
        checked={props.item.isChecked}
        onChange={() => props.handleChange(props.item.id)}
      />
    </div>
  )
}

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      todos: [{ id: 1, line: '1' }, { id: 2, line: '2' }, { id: 3, line: '3' }, { id: 4, line: '4' }]
    }
    this.handleChange = this.handleChange.bind(this)
  }
  handleChange(id) {
    console.log("debug1", id)
    this.setState(prevState => {
      const updatedToDos = prevState.todos.map(todo => {
        // change that i made to clone object inside todos array
        const newtodo = Object.assign({}, todo);
        if (newtodo.id === id) {
          console.log(newtodo.id, id, newtodo.isChecked)
          newtodo.isChecked = !newtodo.isChecked
          console.log(newtodo.id, id, newtodo.isChecked)
        }
        console.log(todo)
        return newtodo
      })
      console.log(updatedToDos)
      return {
        todos: updatedToDos
      }
    })
  }
  render() {
    const todoChecklist = this.state.todos.map(item => <ToDoItm key={item.id} item={item}
      handleChange={this.handleChange.bind(this)} />)
    return (
      <div>
        {todoChecklist}
      </div>
    )
  }
}

export default App;

你看到我如何在 handleChange 函数中克隆那些对象和 return 一个没有引用原始 React 状态的新对象你可以使用不同的方法来克隆内部对象。

检查您的主应用程序是否未环绕严格模式

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);  

StrictMode 两次调用您应用程序的构造函数和其他方法(仅在开发中)以确保没有副作用。尝试删除 StrictMode,看看是否有帮助。

所以,我在 this blog post 上找到了答案。

事实证明,当您使用 npx create-react-app 创建 React 应用程序时, App.js 组件在调用 ReactDOM.Render 时 - 被 React.StrictMode[=18= 包裹]

ReactDOM.render(
  <React.StrictMode>
    <App />,
  </React.StrictMode>,
  document.getElementById('root')
);

关于这个包装器的发行说明说:

React.StrictMode is a wrapper to help prepare apps for async rendering

React.StrictMode 是 re-rendering 应用程序的来源两次,因此是问题的根源。

在博客 post 上,您可以阅读:

One of the benefits that we get from React.StrictMode usage, is that it helps us to detect unexpected side effects in the render-phase lifecycles.

但是生命周期超出了我目前对 React 的了解。

您还可以阅读 React.StrictMode documentation

删除这个包装解决了这个问题。