问题描述
我是React和制作前端应用程序的初学者,所以我决定学习this youtube react tutorial。我对html,js和css有一些了解。
链接导致我遇到问题的课程(在React中练习state
)。问题是:
onChange
分配给复选框的功能在通过以下方式启动应用程序时:npm start
正在起作用... 奇怪。如果执行相同的功能,则可以正常工作:npm run build
,serve -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,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文件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。 我的意思是奇怪-这是我单击第一个复选框时发生的情况:
解决方法
所以基本上你在这里改变了反应状态的原始对象,这不是正确的做法,你需要做的就是在这个todos数组中克隆这些对象。你可以按照下面的代码进行操作。以更有效的方式编写,但对于初学者来说可以,请阅读此https://seaborn.pydata.org/generated/seaborn.scatterplot.html
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,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函数中克隆那些对象并返回没有引用原始React State的newObject,您可以使用其他方法来克隆内部对象。
检查您的主应用程序是否没有包裹在严格模式下
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,document.getElementById('root')
);
StrictMode两次调用您的App的构造函数和其他方法(仅在开发中),以确保没有副作用。尝试删除StrictMode,看看是否有帮助。
,因此,我在this blog post上找到了答案。
事实证明,当您使用以下命令创建React应用时:npx create-react-app
调用ReactDOM.Render时的App.js
组件-被React.StrictMode
包裹
ReactDOM.render(
<React.StrictMode>
<App />,</React.StrictMode>,document.getElementById('root')
);
有关该包装的发行说明说:
React.StrictMode是一个包装程序,可帮助为异步渲染准备应用程序
React.StrictMode是两次重新呈现应用程序的来源,因此是问题的根源。
在博客文章上,您可以阅读:
使用React.StrictMode可以带来的好处之一是,它可以帮助我们检测渲染阶段生命周期中的意外副作用。
但是生命周期超过了我目前对React的了解。
您也可以阅读React.StrictMode documentation。
删除此包装器即可解决此问题。