javascript - React JS - 将静态数组对象从 DBJSON 切换为对象
问题描述
我在下面有这个脚本可以成功运行。此外,您可以在此链接中看到此脚本正在运行:https ://codepen.io/claudio-bitar/pen/VERORW但我更改了一些不起作用的内容,您可以在下面的前面的解释中看到
class TodoApp extends React.Component {
constructor() {
super();
this.state = {
todos: {
"elements": ['a','b','c','d','e','f','g','h','i','j','k']
},
currentPage: 1,
todosPerPage: 3
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
this.setState({
currentPage: Number(event.target.id)
});
}
render() {
const { todos, currentPage, todosPerPage } = this.state;
// Logic for displaying current todos
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = todos.elements.slice(indexOfFirstTodo, indexOfLastTodo);
const renderTodos = currentTodos.map((todo, index) => {
return <li key={index}>{todo}</li>;
});
// Logic for displaying page numbers
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(todos.elements.length / todosPerPage); i++) {
pageNumbers.push(i);
}
const renderPageNumbers = pageNumbers.map(number => {
return (
<li
key={number}
id={number}
onClick={this.handleClick}
>
{number}
</li>
);
});
return (
<div>
<ul>
{renderTodos}
</ul>
<ul id="page-numbers">
{renderPageNumbers}
</ul>
</div>
);
}
}
ReactDOM.render(
<TodoApp />,
document.getElementById('app')
);
所以,我想做同样的事情,但使用来自 DBJson 的对象替换 todos 的数组。因此,我在下面的代码中进行了更改,但没有成功。出现了这个错误信息:
TypeError:无法读取未定义的属性“切片”
import React, { Component } from 'react'
import axios from 'axios'
const URL_TODOS = 'http://localhost:3001/todos';
class Todos extends Component {
constructor(props) {
super(props);
this.state = {
todos: [],
currentPage: 1,
todosPerPage: 3
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
this.setState({
currentPage: Number(event.target.id)
});
}
componentDidMount() {
axios.get(URL_TODOS)
.then(res => {
this.setState({ todos: res.data })
})
}
render() {
const { todos, currentPage, todosPerPage } = this.state;
// Logic for displaying current todos
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = todos.elements.slice(indexOfFirstTodo, indexOfLastTodo);
const renderTodos = currentTodos.map((todo, index) => {
return <li key={index}>{todo}</li>;
});
// Logic for displaying page numbers
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(todos.elements.length / todosPerPage); i++) {
pageNumbers.push(i);
}
const renderPageNumbers = pageNumbers.map(number => {
return (
<li
key={number}
id={number}
onClick={this.handleClick}
>
{number}
</li>
);
});
return (
<div>
<ul>
{renderTodos}
</ul>
<ul id="page-numbers">
{renderPageNumbers}
</ul>
</div>
);
}
}
export default Todos
这是我的DBJson文件:
"todos": [
{
"elements": [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k"
]
}
]
我也接受建议如何更轻松地做到这一点。也许改变json结构?我不知道。
解决方案
根据您的 DBJson 文件,您似乎正在接收一个带有对象的数组和一个数组:
"todos": [
{
"elements": [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k"
]
}
]
因此,获取 todos 的第一个元素:
todos[0]
使用异步/等待
在使用 Axios 时,我总是尝试使用 async await,如下所示:
async componentDidMount() {
try {
let res = await axios.get(URL_TODOS);
let response = await res.data;
this.setState({ todos: response.todos[0] });
} catch(error) {
console.error(error);
}
}
在设置数据之前,您必须等待承诺解决。
然后,从该对象中获取元素。
const { todos, currentPage, todosPerPage } = this.state;
// Logic for displaying current todos
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = todos.elements.slice(indexOfFirstTodo, indexOfLastTodo);
没有异步/等待
如果您不想使用异步/等待:
componentDidMount() {
axios.get(URL_TODOS)
.then(response => response.data)
.then(data => {
this.setState({ todos: data[0] })
})
.catch(error => { console.error(error) });
}
axios 中的更多信息和示例
在这个答案中,我添加了一些关于 fetch 和 axios 的信息和差异,如果你没有得到正确类型的响应,有一些关于使用 axios 的代码可能会对你有所帮助。看看它是否也有帮助。
为什么使用 componentDidMount
来自官方文档:
componentDidMount() 在组件安装后立即调用(插入到树中)。需要 DOM 节点的初始化应该放在这里。如果您需要从远程端点加载数据,这是实例化网络请求的好地方。
此方法是设置任何订阅的好地方。如果你这样做了,不要忘记在 componentWillUnmount() 中取消订阅。
您可以立即在 componentDidMount() 中调用 setState()。它会触发额外的渲染,但会在浏览器更新屏幕之前发生。这保证了即使在这种情况下 render() 将被调用两次,用户也不会看到中间状态。请谨慎使用此模式,因为它通常会导致性能问题。在大多数情况下,您应该能够在 constructor() 中分配初始状态。但是,对于模态和工具提示等情况,当您需要在渲染取决于其大小或位置的内容之前测量 DOM 节点时,它可能是必要的。
为什么不使用 componentWillMount
来自官方文档
UNSAFE_componentWillMount() 在挂载之前被调用。它在 render() 之前调用,因此在该方法中同步调用 setState() 不会触发额外的渲染。通常,我们建议使用 constructor() 来代替初始化状态。
避免在此方法中引入任何副作用或订阅。对于这些用例,请改用 componentDidMount()。
推荐阅读
- shell - 当我尝试在 git bash 中使用“ls”时,我得到了“desktop.ini”的答案
- azure - How to enable Implicit grant in Azure Active Directory
- download - 文件下载后回发不起作用
- android - Lombok @RequiredArgsConstructor 在Android 中不起作用,但@AllArgsConstructor 起作用
- tensorflow - Inspecting Tensorflow graph
- javascript - 将 const 函数代码从 JSX 转换为 TSX
- django - django-select2 小部件的查询集被忽略
- javascript - 引导验证器的成功功能不起作用?
- powerbi - 在列表列中查找的 DAX 不同字符串
- python-3.x - QPython Android PySpeedTest