React 构建在生产中产生错误
React build creates errors in production
我是 React 的新手,我已经学习了 ToDo 网络应用程序的教程。完成后,我在终端中没有错误地构建它用于生产。当我尝试使用 serve -s build
静态打开以便在本地查看时,会出现此问题。最初,我瞥见了内容,然后弹出了两个在 npm start server
开发中不存在的错误。
错误是:
react-dom.production.min.js:209 TypeError: Cannot read property 'length' of null
at App.js:31
at ro (react-dom.production.min.js:211)
at vu (react-dom.production.min.js:257)
at t.unstable_runWithPriority (scheduler.production.min.js:19)
at Wl (react-dom.production.min.js:122)
at hu (react-dom.production.min.js:257)
at react-dom.production.min.js:256
at j (scheduler.production.min.js:17)
at MessagePort.E.port1.onmessage (scheduler.production.min.js:14)
Za @ react-dom.production.min.js:209
scheduler.production.min.js:14 Uncaught TypeError: Cannot read property 'length' of null
at App.js:31
at ro (react-dom.production.min.js:211)
at vu (react-dom.production.min.js:257)
at t.unstable_runWithPriority (scheduler.production.min.js:19)
at Wl (react-dom.production.min.js:122)
at hu (react-dom.production.min.js:257)
at react-dom.production.min.js:256
at j (scheduler.production.min.js:17)
at MessagePort.E.port1.onmessage (scheduler.production.min.js:14)
从消息中我了解到故障部分在我的
App.js
import React, { useState } from "react";
import "./App.css";
//Importing Components
import Form from "./Components/Form";
import ToDoList from "./Components/ToDoList";
function App() {
// eslint-disable-next-line
const [inputText, setInputText] = useState("");
const [todos, setTodos] = useState([]);
const [status, setStatus] = useState("");
const [filterTodos, setFilterTodos] = useState([]);
const getLocalTodos = () => {
setTodos(JSON.parse(localStorage.getItem("todos")));
};
React.useEffect(() => {
switch (status) {
case "completed":
setFilterTodos(todos.filter((todo) => todo.completed === true));
break;
case "uncompleted":
setFilterTodos(todos.filter((todo) => todo.completed === false));
break;
default:
setFilterTodos(todos);
break;
}
if (todos.length !== 0) {
localStorage.setItem("todos", JSON.stringify(todos));
}
}, [todos, status]);
React.useEffect(() => {
getLocalTodos();
}, []);
return (
<React.Fragment>
<header>{inputText}</header>
<Form
setStatus={setStatus}
todos={todos}
setTodos={setTodos}
InputText={inputText}
setInputText={setInputText}
/>
<ToDoList filterTodos={filterTodos} setTodos={setTodos} todos={todos} />
</React.Fragment>
);
}
export default App;
我将数据保存到 localStorage 的部分。我正在检查数组是否为零,以防止 useEffect 在第一次加载时清空 localStorage 数据。
如何解决生产版本中的问题?
下面我附上了其余的代码:
ToDoList.js
import React from "react";
import ToDo from "./ToDo";
const ToDoList = (props) => {
return (
<div className="todo-container">
<ul className="todo-list">
{props.filterTodos.map((todo) => {
return (
<ToDo
todo={todo}
todos={props.todos}
setTodos={props.setTodos}
key={todo.id}
text={todo.text}
/>
);
})}
</ul>
</div>
);
};
export default ToDoList;
ToDo.js
import React from "react"
const ToDo = props => {
const deleteNote = () => {
props.setTodos(props.todos.filter(e=>e.id !== props.todo.id))
}
const completedHandler = () =>{
props.setTodos(
props.todos.map(item =>{
if(item.id === props.todo.id){
return {
...item, completed: !item.completed
}
}
return item
})
)
}
return (
<div className="ToDo">
<li className={`todo-item ${props.todo.completed ? "cool" : "notCool"}`}>{props.text}</li>
<button onClick={completedHandler} className='complete-btn'>
Complete </button>
<button onClick={deleteNote} className='trash-btn'>
Trash </button>
</div>
)
}
export default ToDo
Form.js
import React from "react";
const Form = (props) => {
const InputTextHandler = (e) => {
props.setInputText(e.target.value);
};
const addNote = (e) => {
e.preventDefault();
props.setTodos([
...props.todos,
{ text: props.InputText, completed: false, id: Math.random() },
]);
props.setInputText("");
console.log(props.InputText);
};
const statusHanlder = (e) => {
props.setStatus(e.target.value);
};
return (
<form>
<input
value={props.InputText}
onChange={InputTextHandler}
type="text"
className="todo-input"
/>
<button onClick={addNote} className="todo-button" type="submit">
<i className="fas fa-plus-square">+</i>
</button>
<div className="select">
<select onChange={statusHanlder} name="todos" className="filter-todo">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="uncompleted">Uncompleted</option>
</select>
</div>
</form>
);
};
export default Form;
发展观
静态本地服务器中的生产版本
您确定您的 localStorage 中有待办事项吗?
此函数假定您的 localStorage 中有待办事项,但可能没有。
const getLocalTodos = () => {
setTodos(JSON.parse(localStorage.getItem("todos")));
};
localStorage 中没有您的待办事项
JSON.parse(localStorage.getItem("todos")) // returns undefined.
这弄乱了你的 todos 状态,它本来是一个数组。
因此 .length
of undefined.
如果 localStorage 中没有 todos 字段,则使用 getLocalTodos 调用的 useEffect 会为 todos 状态设置“空”值。
只需像这样更改 getLocalTodos:
const getLocalTodos = () => {
setTodos(JSON.parse(localStorage.getItem("todos")) || []);
};
第一次渲染App时。您从 localStorage 获取待办事项列表。但它没什么。所以,你的代码总是设置 todos 并且那个案例 totos 将是 null
.
组件应用应该检查:
const getLocalTodos = () => {
const cached = localStorage.getItem("todos") ? JSON.parse(localStorage.getItem("todos")) : null;
if (cached === null)
return;
setTodos(cached);
};
我是 React 的新手,我已经学习了 ToDo 网络应用程序的教程。完成后,我在终端中没有错误地构建它用于生产。当我尝试使用 serve -s build
静态打开以便在本地查看时,会出现此问题。最初,我瞥见了内容,然后弹出了两个在 npm start server
开发中不存在的错误。
错误是:
react-dom.production.min.js:209 TypeError: Cannot read property 'length' of null
at App.js:31
at ro (react-dom.production.min.js:211)
at vu (react-dom.production.min.js:257)
at t.unstable_runWithPriority (scheduler.production.min.js:19)
at Wl (react-dom.production.min.js:122)
at hu (react-dom.production.min.js:257)
at react-dom.production.min.js:256
at j (scheduler.production.min.js:17)
at MessagePort.E.port1.onmessage (scheduler.production.min.js:14)
Za @ react-dom.production.min.js:209
scheduler.production.min.js:14 Uncaught TypeError: Cannot read property 'length' of null
at App.js:31
at ro (react-dom.production.min.js:211)
at vu (react-dom.production.min.js:257)
at t.unstable_runWithPriority (scheduler.production.min.js:19)
at Wl (react-dom.production.min.js:122)
at hu (react-dom.production.min.js:257)
at react-dom.production.min.js:256
at j (scheduler.production.min.js:17)
at MessagePort.E.port1.onmessage (scheduler.production.min.js:14)
从消息中我了解到故障部分在我的
App.js
import React, { useState } from "react";
import "./App.css";
//Importing Components
import Form from "./Components/Form";
import ToDoList from "./Components/ToDoList";
function App() {
// eslint-disable-next-line
const [inputText, setInputText] = useState("");
const [todos, setTodos] = useState([]);
const [status, setStatus] = useState("");
const [filterTodos, setFilterTodos] = useState([]);
const getLocalTodos = () => {
setTodos(JSON.parse(localStorage.getItem("todos")));
};
React.useEffect(() => {
switch (status) {
case "completed":
setFilterTodos(todos.filter((todo) => todo.completed === true));
break;
case "uncompleted":
setFilterTodos(todos.filter((todo) => todo.completed === false));
break;
default:
setFilterTodos(todos);
break;
}
if (todos.length !== 0) {
localStorage.setItem("todos", JSON.stringify(todos));
}
}, [todos, status]);
React.useEffect(() => {
getLocalTodos();
}, []);
return (
<React.Fragment>
<header>{inputText}</header>
<Form
setStatus={setStatus}
todos={todos}
setTodos={setTodos}
InputText={inputText}
setInputText={setInputText}
/>
<ToDoList filterTodos={filterTodos} setTodos={setTodos} todos={todos} />
</React.Fragment>
);
}
export default App;
我将数据保存到 localStorage 的部分。我正在检查数组是否为零,以防止 useEffect 在第一次加载时清空 localStorage 数据。 如何解决生产版本中的问题?
下面我附上了其余的代码:
ToDoList.js
import React from "react";
import ToDo from "./ToDo";
const ToDoList = (props) => {
return (
<div className="todo-container">
<ul className="todo-list">
{props.filterTodos.map((todo) => {
return (
<ToDo
todo={todo}
todos={props.todos}
setTodos={props.setTodos}
key={todo.id}
text={todo.text}
/>
);
})}
</ul>
</div>
);
};
export default ToDoList;
ToDo.js
import React from "react"
const ToDo = props => {
const deleteNote = () => {
props.setTodos(props.todos.filter(e=>e.id !== props.todo.id))
}
const completedHandler = () =>{
props.setTodos(
props.todos.map(item =>{
if(item.id === props.todo.id){
return {
...item, completed: !item.completed
}
}
return item
})
)
}
return (
<div className="ToDo">
<li className={`todo-item ${props.todo.completed ? "cool" : "notCool"}`}>{props.text}</li>
<button onClick={completedHandler} className='complete-btn'>
Complete </button>
<button onClick={deleteNote} className='trash-btn'>
Trash </button>
</div>
)
}
export default ToDo
Form.js
import React from "react";
const Form = (props) => {
const InputTextHandler = (e) => {
props.setInputText(e.target.value);
};
const addNote = (e) => {
e.preventDefault();
props.setTodos([
...props.todos,
{ text: props.InputText, completed: false, id: Math.random() },
]);
props.setInputText("");
console.log(props.InputText);
};
const statusHanlder = (e) => {
props.setStatus(e.target.value);
};
return (
<form>
<input
value={props.InputText}
onChange={InputTextHandler}
type="text"
className="todo-input"
/>
<button onClick={addNote} className="todo-button" type="submit">
<i className="fas fa-plus-square">+</i>
</button>
<div className="select">
<select onChange={statusHanlder} name="todos" className="filter-todo">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="uncompleted">Uncompleted</option>
</select>
</div>
</form>
);
};
export default Form;
发展观
您确定您的 localStorage 中有待办事项吗?
此函数假定您的 localStorage 中有待办事项,但可能没有。
const getLocalTodos = () => {
setTodos(JSON.parse(localStorage.getItem("todos")));
};
localStorage 中没有您的待办事项
JSON.parse(localStorage.getItem("todos")) // returns undefined.
这弄乱了你的 todos 状态,它本来是一个数组。
因此 .length
of undefined.
如果 localStorage 中没有 todos 字段,则使用 getLocalTodos 调用的 useEffect 会为 todos 状态设置“空”值。
只需像这样更改 getLocalTodos:
const getLocalTodos = () => {
setTodos(JSON.parse(localStorage.getItem("todos")) || []);
};
第一次渲染App时。您从 localStorage 获取待办事项列表。但它没什么。所以,你的代码总是设置 todos 并且那个案例 totos 将是 null
.
组件应用应该检查:
const getLocalTodos = () => {
const cached = localStorage.getItem("todos") ? JSON.parse(localStorage.getItem("todos")) : null;
if (cached === null)
return;
setTodos(cached);
};