从 React 功能组件中调用 API
Making API calls out of React Functional Component
我是 React 的新手,我知道函数式和 Class 组件的概念以及 useEffect 和 useState 等 Hook;因此,我在将这些知识付诸实践时遇到了麻烦,因为我正在研究以下 React 组件,该组件进行了简单的 Javascript API 调用,我现在想将其转换为“真实的”React API调用,使用State和Hooks。
我的问题如下:我想呈现 API 返回的员工对象,从员工的名字和姓氏开始,然后是其他信息。
对 API 的请求在 Javascript 中正常进行,并且 returns 需要数据;因此,我不太确定根据定义将状态设置为什么(0?假?其他?这取决于什么,我怎么知道?)。
代码如下:
import React, {useEffect, useState} from 'react';
import { Link } from "react-router-dom";
import {
Container,
Row,
Col,
Card,
CardBody,
Table,
Button, Alert, Modal, ModalHeader, ModalBody
} from "reactstrap";
const ContactsList = (props) => {
let request = new XMLHttpRequest()
// Open a new connection, using the GET request on the URL endpoint
request.open('GET', 'https://somenet.net/employee', true)
request.onload = function () {
// Begin accessing JSON data here
let data = JSON.parse(this.response)
data.forEach((employee) => {
// Log each movie's title
console.log(employee.id, employee.firstname, employee.lastname, employee.performance_index, employee.min_customer_distance, employee.customer_distance_radius, employee.webfleet_obj_id, employee.default_employee_working_schedule_id)
})
}
// Send request
request.send()
let employees = [
{
id: 1, img: "Null", name: "David McHenry", designation: "UI/UX Designer", email: "david@skote.com", projects: "125",
skills: [
{ name: "Photoshop" },
{ name: "illustrator" }
]
}
]
const users = [
{
id: 1, img: "Null", name: "David McHenry", designation: "UI/UX Designer", email: "david@skote.com", projects: "125",
skills: [
{ name: "Photoshop" },
{ name: "illustrator" }
]
},
{
id: 2, img: avatar2, name: "Frank Kirk", designation: "Frontend Developer", email: "frank@skote.com", projects: "132",
skills: [
{ name: "Html" },
{ name: "Css" },
{ name: "2 + more" },
]
},
{
id: 3, img: avatar3, name: "Rafael Morales", designation: "Backend Developer", email: "Rafael@skote.com", projects: "1112",
skills: [
{ name: "Php" },
{ name: "Java" },
{ name: "Python" },
]
},
{
id: 4, img: "Null", name: "Mark Ellison", designation: "Full Stack Developer", email: "mark@skote.com", projects: "121",
skills: [
{ name: "Ruby" },
{ name: "Php" },
{ name: "2 + more" },
]
},
{
id: 5, img: avatar4, name: "Minnie Walter", designation: "Frontend Developer", email: "minnie@skote.com", projects: "145",
skills: [
{ name: "Html" },
{ name: "Css" },
{ name: "2 + more" },
]
},
{
id: 6, img: avatar5, name: "Shirley Smith", designation: "UI/UX Designer", email: "shirley@skote.com", projects: "136",
skills: [
{ name: "Photoshop" },
{ name: "UI/UX Designer" }
]
},
{
id: 7, img: "Null", name: "John Santiago", designation: "Full Stack Developer", email: "john@skote.com", projects: "125",
skills: [
{ name: "Ruby" },
{ name: "Php" },
{ name: "2 + more" },
]
},
{
id: 8, img: avatar7, name: "Colin Melton", designation: "Backend Developer", email: "colin@skote.com", projects: "136",
skills: [
{ name: "Php" },
{ name: "Java" },
{ name: "Python" },
]
},
];
const DefaultEvents = [{
id: 1,
title: 'Hey!',
start: new Date().setDate(new Date().getDate() + 1),
className: 'bg-warning text-white'
},
{
id: 2,
title: 'See John Deo',
start: new Date(),
end: new Date(),
className: 'bg-success text-white'
},
{
id: 3,
title: 'Meet John Deo',
start: new Date().setDate(new Date().getDate() + 8),
className: 'bg-info text-white'
},
{
id: 4,
title: 'Buy a Theme',
start: new Date().setDate(new Date().getDate() + 7),
className: 'bg-primary text-white'
}];
const DefaultCategories = [
{
id: 1,
title: 'New Theme Release',
type: 'success'
},
{
id: 2,
title: 'My Event',
type: 'info'
},
{
id: 3,
title: 'Meet Manager',
type: 'warning'
},
{
id: 4,
title: 'Report Error',
type: 'danger'
},
];
const event1= { id: 0, title: "", title_category: "", start: "", className: "", category: "", event_category: "" };
const [calendarEvents, setCalendarEvents] = useState(DefaultEvents);
const [categories, setCategories] = useState(DefaultCategories);
const [modal, setModal] = useState(false);
const [modal1, setModal1] = useState(false);
const [modalcategory, setModalcategory] = useState(false);
const [event, setEvent] = useState(event1);
const [selectedDay, setSelectedDay] = useState(0);
const title_category = false;
const calendarComponentRef = React.createRef();
useEffect(() => {
new Draggable(document.getElementById("external-events"), {
itemSelector: '.external-event',
});
});
/**
* Handling the modal state
*/
function toggle() {
setModal(!modal)
}
function toggle1() {
setModal1(!modal1)
}
function togglecategory() {
setModalcategory(!modalcategory)
}
/**
* Handling date click on calendar
*/
const handleDateClick = (arg) => {
setSelectedDay(arg);
toggle();
}
/**
* Handling click on event on calendar
*/
const handleEventClick = (arg) => {
const eventNew = arg.event;
const event_tmp = { id: eventNew.id, title: eventNew.title, title_category: eventNew.title_category, start: eventNew.start, className: eventNew.classNames, category: eventNew.classNames[0], event_category: eventNew.classNames[0] };
setEvent(event_tmp);
toggle1();
}
/**
* Handling submit event on event form
*/
const handleValidEventSubmit = (e, values) => {
var newEvent = {};
newEvent = {
id: calendarEvents.length + 1,
title: values['title'],
start: selectedDay ? selectedDay.date : new Date(),
className: values.category + ' text-white'
};
// save new event
setCalendarEvents(calendarEvents.concat(newEvent));
setSelectedDay(null);
toggle();
}
const handleValidEventSubmitEvent = (e, values) => {
var newEvent = {};
newEvent = { id: event.id, title: values.title, classNames: values.category + ' text-white', start: event.start };
//first, remove array item, which we want to edit
let filteredArray = calendarEvents.filter(item => item.id + "" !== event.id + "");
//then concat update item details
let NewArray = filteredArray.concat(newEvent);
//store to state
setCalendarEvents(NewArray);
setEvent(null);
setSelectedDay(null);
toggle1();
}
const handleValidEventSubmitcategory = (e, values) => {
var newEvent = {};
newEvent = {
id: calendarEvents.length + 1,
title: values['title_category'],
type: values.event_category
};
// categories.concat(newEvent);
setCategories(categories.concat(newEvent));
togglecategory();
}
/**
* On calendar drop event
*/
const onDrop = (event) => {
const draggedEl = event.draggedEl;
var newEvent = {
id: calendarEvents.length + 1,
title: draggedEl.innerText,
start: event.date,
className: draggedEl.getAttribute('data-type') + ' text-white'
};
// save new event
setCalendarEvents(calendarEvents.concat(newEvent));
}
return (
<React.Fragment>
<div className="page-content">
<Container fluid>
{/* Render Breadcrumbs */}
<Breadcrumbs title="Contacts" breadcrumbItem="Users List" />
<Card>
<CardBody>
<Row>
<Col lg={3}>
<Button color="primary" className="font-16 btn-block" onClick={() => togglecategory() }>
<i className="mdi mdi-plus-circle-outline"></i> Create New Event
</Button>
<div id="external-events" className="mt-3">
<p className="text-muted">Drag and drop your event or click in the calendar</p>
{categories.map((category, i) => {
return <Alert color={category.type}>{category.title} </Alert>
})}
</div>
</Col>
<Col className="col-lg-3">
<div className="table-responsive">
<Table className="table-centered table-nowrap table-hover">
<thead className="thead-light">
<tr>
<th scope="col" style={{ width: "70px" }}>#</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{
employees.map((user, i) =>
<tr key={"_user_" + i} >
<td>
{
user.img === "Null"
? <div className="avatar-xs">
<span className="avatar-title rounded-circle">
{user.name.charAt(0)}
</span>
</div>
: <div>
<img className="rounded-circle avatar-xs" src={user.img} alt="" />
</div>
}
</td>
<td>
<h5 className="font-size-14 mb-1"><Link to="#" className="text-dark">{user.name}</Link></h5>
<p className="text-muted mb-0">{user.designation}</p>
</td>
</tr>
)
}
</tbody>
</Table>
</div>
</Col>
<Col className="col-lg-6">
{/* fullcalendar control */}
<FullCalendar ref={calendarComponentRef} defaultView="dayGridMonth" plugins={[BootstrapTheme, dayGridPlugin, interactionPlugin]}
slotDuration={'00:15:00'}
minTime={'08:00:00'}
maxTime={'19:00:00'}
handleWindowResize={true}
themeSystem="bootstrap"
header={{
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay'
}}
events={calendarEvents}
editable={true}
droppable={true}
eventLimit={true}
selectable={true}
dateClick={handleDateClick}
eventClick={handleEventClick}
drop={onDrop}
id="calendar" />
<button onClick={() => togglecategory() }
className="btn btn-secondary float-right btn-lg waves-effect btn btn-secondary">
Neuen Termin anlegen
</button>
{/* New event modal */}
<Modal isOpen={modal} toggle={() => toggle()} className="">
<ModalHeader toggle={() => toggle()} tag="h4">
Add Event
</ModalHeader>
<ModalBody>
<AvForm onValidSubmit={handleValidEventSubmit}>
<Row form>
<Col className="col-12">
<AvField name="title" label="Event Name" type="text" errorMessage="Invalid name" validate={{
required: { value: true }
}} value={event ? event.title : ''} />
</Col>
<Col className="col-12">
<AvField type="select" name="category" label="Select Category"
value={event ? event.category : 'bg-primary'}>
<option value="bg-danger">Danger</option>
<option value="bg-success">Success</option>
<option value="bg-primary">Primary</option>
<option value="bg-info">Info</option>
<option value="bg-dark">Dark</option>
<option value="bg-warning">Warning</option>
</AvField>
</Col>
</Row>
<Row>
<Col>
<div className="text-right">
<button type="button" className="btn btn-light mr-2" onClick={() => toggle()}>Close</button>
<button type="submit" className="btn btn-success save-event">Save</button>
</div>
</Col>
</Row>
</AvForm>
</ModalBody>
</Modal>
{/* edit event modal */}
<Modal isOpen={modal1} toggle={() => toggle1()} className="">
<ModalHeader toggle={() => toggle1()} tag="h4">
Edit Event
</ModalHeader>
<ModalBody>
<AvForm onValidSubmit={handleValidEventSubmitEvent}>
<Row form>
<Col className="col-12">
<AvField name="title" label="Event Name" type="text" errorMessage="Invalid name" validate={{
required: { value: true }
}} value={event ? event.title : ''} />
</Col>
<Col className="col-12">
<AvField type="select" name="category" label="Select Category"
value={event ? event.category : 'bg-primary'}>
<option value="bg-danger">Danger</option>
<option value="bg-success">Success</option>
<option value="bg-primary">Primary</option>
<option value="bg-info">Info</option>
<option value="bg-dark">Dark</option>
<option value="bg-warning">Warning</option>
</AvField>
</Col>
</Row>
<Row>
<Col>
<div className="text-right">
<button type="button" className="btn btn-light mr-2" onClick={() => toggle()}>Close</button>
<button type="submit" className="btn btn-success save-event">Save</button>
</div>
</Col>
</Row>
</AvForm>
</ModalBody>
</Modal>
<Modal isOpen={modalcategory} toggle={() => togglecategory()} className="">
<ModalHeader toggle={() => togglecategory()} tag="h4">
Add a category
</ModalHeader>
<ModalBody>
<AvForm onValidSubmit={handleValidEventSubmitcategory}>
<Row form>
<Col className="col-12">
<AvField name="title_category" label="Category Name" type="text" errorMessage="Invalid name" validate={{
required: { value: true }
}} value={title_category ? event.title_category : ''} />
</Col>
<Col className="col-12">
<AvField type="select" name="event_category" label="Choose Category Color"
value={event ? event.event_category : 'bg-primary'}>
<option value="bg-danger">Danger</option>
<option value="bg-success">Success</option>
<option value="bg-primary">Primary</option>
<option value="bg-info">Info</option>
<option value="bg-dark">Dark</option>
<option value="bg-warning">Warning</option>
</AvField>
</Col>
</Row>
<Row>
<Col>
<div className="text-right">
<button type="button" className="btn btn-light mr-2" onClick={() => togglecategory()}>Close</button>
<button type="submit" className="btn btn-success save-event">Save</button>
</div>
</Col>
</Row>
</AvForm>
</ModalBody>
</Modal>
</Col>
</Row>
</CardBody>
</Card>
</Container>
</div>
</React.Fragment>
);
}
export default ContactsList;
任何提示或帮助将不胜感激 - 提前致谢!
几件事:
- 您不应在函数本身中获取数据 - 这将在每次组件呈现时触发获取。通常,您希望在组件首次呈现时开始获取:
useEffect(() => {
fetchData().then(response => {
const employees = JSON.parse(response)
setEmployees(employees)
})
}, [])
另见这个问题:
现在我们有了正确的方法来获取数据,我们开始讨论另一个问题 - what to set the state to by definition
。也就是说,如何初始化数据。人们可能会告诉你它可以是任何东西,但实际上,如果你正在使用一个数组(你正在迭代 employees 对象,所以我假设它是一个数组),最好用一个空数组初始化它.这样类型就不会改变,下面的 JSX 不需要额外的条件逻辑来处理不同类型的员工。
const [employees, setEmployees] = useState([])
我通常先调用useState,然后再调用useEffect。实际上,如果你交换它们,不确定它是否会破裂。所以总代码为:
const fetchData = async () => {
const res = await fetch('https://swapi.dev/api/people/')
const json = await res.json()
return json.result
}
const ContactsList = props => {
const [employees, setEmployees] = useState([])
useEffect(() => {
fetchData().then(employees => {
setEmployees(employees)
})
}, [])
return (
<div>
{employees.map(employee => <div key={employee.id}>{employee.name}</div>)}
</div>
)
}
更笼统的说明:
- 你的组件很大。 React 的美妙之处在于你可以将它分成子组件。这不仅对您自己是个好习惯,而且其他 Whosebug 用户也更容易理解您的问题。只在组件中保留真正需要的东西。
我是 React 的新手,我知道函数式和 Class 组件的概念以及 useEffect 和 useState 等 Hook;因此,我在将这些知识付诸实践时遇到了麻烦,因为我正在研究以下 React 组件,该组件进行了简单的 Javascript API 调用,我现在想将其转换为“真实的”React API调用,使用State和Hooks。
我的问题如下:我想呈现 API 返回的员工对象,从员工的名字和姓氏开始,然后是其他信息。
对 API 的请求在 Javascript 中正常进行,并且 returns 需要数据;因此,我不太确定根据定义将状态设置为什么(0?假?其他?这取决于什么,我怎么知道?)。
代码如下:
import React, {useEffect, useState} from 'react';
import { Link } from "react-router-dom";
import {
Container,
Row,
Col,
Card,
CardBody,
Table,
Button, Alert, Modal, ModalHeader, ModalBody
} from "reactstrap";
const ContactsList = (props) => {
let request = new XMLHttpRequest()
// Open a new connection, using the GET request on the URL endpoint
request.open('GET', 'https://somenet.net/employee', true)
request.onload = function () {
// Begin accessing JSON data here
let data = JSON.parse(this.response)
data.forEach((employee) => {
// Log each movie's title
console.log(employee.id, employee.firstname, employee.lastname, employee.performance_index, employee.min_customer_distance, employee.customer_distance_radius, employee.webfleet_obj_id, employee.default_employee_working_schedule_id)
})
}
// Send request
request.send()
let employees = [
{
id: 1, img: "Null", name: "David McHenry", designation: "UI/UX Designer", email: "david@skote.com", projects: "125",
skills: [
{ name: "Photoshop" },
{ name: "illustrator" }
]
}
]
const users = [
{
id: 1, img: "Null", name: "David McHenry", designation: "UI/UX Designer", email: "david@skote.com", projects: "125",
skills: [
{ name: "Photoshop" },
{ name: "illustrator" }
]
},
{
id: 2, img: avatar2, name: "Frank Kirk", designation: "Frontend Developer", email: "frank@skote.com", projects: "132",
skills: [
{ name: "Html" },
{ name: "Css" },
{ name: "2 + more" },
]
},
{
id: 3, img: avatar3, name: "Rafael Morales", designation: "Backend Developer", email: "Rafael@skote.com", projects: "1112",
skills: [
{ name: "Php" },
{ name: "Java" },
{ name: "Python" },
]
},
{
id: 4, img: "Null", name: "Mark Ellison", designation: "Full Stack Developer", email: "mark@skote.com", projects: "121",
skills: [
{ name: "Ruby" },
{ name: "Php" },
{ name: "2 + more" },
]
},
{
id: 5, img: avatar4, name: "Minnie Walter", designation: "Frontend Developer", email: "minnie@skote.com", projects: "145",
skills: [
{ name: "Html" },
{ name: "Css" },
{ name: "2 + more" },
]
},
{
id: 6, img: avatar5, name: "Shirley Smith", designation: "UI/UX Designer", email: "shirley@skote.com", projects: "136",
skills: [
{ name: "Photoshop" },
{ name: "UI/UX Designer" }
]
},
{
id: 7, img: "Null", name: "John Santiago", designation: "Full Stack Developer", email: "john@skote.com", projects: "125",
skills: [
{ name: "Ruby" },
{ name: "Php" },
{ name: "2 + more" },
]
},
{
id: 8, img: avatar7, name: "Colin Melton", designation: "Backend Developer", email: "colin@skote.com", projects: "136",
skills: [
{ name: "Php" },
{ name: "Java" },
{ name: "Python" },
]
},
];
const DefaultEvents = [{
id: 1,
title: 'Hey!',
start: new Date().setDate(new Date().getDate() + 1),
className: 'bg-warning text-white'
},
{
id: 2,
title: 'See John Deo',
start: new Date(),
end: new Date(),
className: 'bg-success text-white'
},
{
id: 3,
title: 'Meet John Deo',
start: new Date().setDate(new Date().getDate() + 8),
className: 'bg-info text-white'
},
{
id: 4,
title: 'Buy a Theme',
start: new Date().setDate(new Date().getDate() + 7),
className: 'bg-primary text-white'
}];
const DefaultCategories = [
{
id: 1,
title: 'New Theme Release',
type: 'success'
},
{
id: 2,
title: 'My Event',
type: 'info'
},
{
id: 3,
title: 'Meet Manager',
type: 'warning'
},
{
id: 4,
title: 'Report Error',
type: 'danger'
},
];
const event1= { id: 0, title: "", title_category: "", start: "", className: "", category: "", event_category: "" };
const [calendarEvents, setCalendarEvents] = useState(DefaultEvents);
const [categories, setCategories] = useState(DefaultCategories);
const [modal, setModal] = useState(false);
const [modal1, setModal1] = useState(false);
const [modalcategory, setModalcategory] = useState(false);
const [event, setEvent] = useState(event1);
const [selectedDay, setSelectedDay] = useState(0);
const title_category = false;
const calendarComponentRef = React.createRef();
useEffect(() => {
new Draggable(document.getElementById("external-events"), {
itemSelector: '.external-event',
});
});
/**
* Handling the modal state
*/
function toggle() {
setModal(!modal)
}
function toggle1() {
setModal1(!modal1)
}
function togglecategory() {
setModalcategory(!modalcategory)
}
/**
* Handling date click on calendar
*/
const handleDateClick = (arg) => {
setSelectedDay(arg);
toggle();
}
/**
* Handling click on event on calendar
*/
const handleEventClick = (arg) => {
const eventNew = arg.event;
const event_tmp = { id: eventNew.id, title: eventNew.title, title_category: eventNew.title_category, start: eventNew.start, className: eventNew.classNames, category: eventNew.classNames[0], event_category: eventNew.classNames[0] };
setEvent(event_tmp);
toggle1();
}
/**
* Handling submit event on event form
*/
const handleValidEventSubmit = (e, values) => {
var newEvent = {};
newEvent = {
id: calendarEvents.length + 1,
title: values['title'],
start: selectedDay ? selectedDay.date : new Date(),
className: values.category + ' text-white'
};
// save new event
setCalendarEvents(calendarEvents.concat(newEvent));
setSelectedDay(null);
toggle();
}
const handleValidEventSubmitEvent = (e, values) => {
var newEvent = {};
newEvent = { id: event.id, title: values.title, classNames: values.category + ' text-white', start: event.start };
//first, remove array item, which we want to edit
let filteredArray = calendarEvents.filter(item => item.id + "" !== event.id + "");
//then concat update item details
let NewArray = filteredArray.concat(newEvent);
//store to state
setCalendarEvents(NewArray);
setEvent(null);
setSelectedDay(null);
toggle1();
}
const handleValidEventSubmitcategory = (e, values) => {
var newEvent = {};
newEvent = {
id: calendarEvents.length + 1,
title: values['title_category'],
type: values.event_category
};
// categories.concat(newEvent);
setCategories(categories.concat(newEvent));
togglecategory();
}
/**
* On calendar drop event
*/
const onDrop = (event) => {
const draggedEl = event.draggedEl;
var newEvent = {
id: calendarEvents.length + 1,
title: draggedEl.innerText,
start: event.date,
className: draggedEl.getAttribute('data-type') + ' text-white'
};
// save new event
setCalendarEvents(calendarEvents.concat(newEvent));
}
return (
<React.Fragment>
<div className="page-content">
<Container fluid>
{/* Render Breadcrumbs */}
<Breadcrumbs title="Contacts" breadcrumbItem="Users List" />
<Card>
<CardBody>
<Row>
<Col lg={3}>
<Button color="primary" className="font-16 btn-block" onClick={() => togglecategory() }>
<i className="mdi mdi-plus-circle-outline"></i> Create New Event
</Button>
<div id="external-events" className="mt-3">
<p className="text-muted">Drag and drop your event or click in the calendar</p>
{categories.map((category, i) => {
return <Alert color={category.type}>{category.title} </Alert>
})}
</div>
</Col>
<Col className="col-lg-3">
<div className="table-responsive">
<Table className="table-centered table-nowrap table-hover">
<thead className="thead-light">
<tr>
<th scope="col" style={{ width: "70px" }}>#</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{
employees.map((user, i) =>
<tr key={"_user_" + i} >
<td>
{
user.img === "Null"
? <div className="avatar-xs">
<span className="avatar-title rounded-circle">
{user.name.charAt(0)}
</span>
</div>
: <div>
<img className="rounded-circle avatar-xs" src={user.img} alt="" />
</div>
}
</td>
<td>
<h5 className="font-size-14 mb-1"><Link to="#" className="text-dark">{user.name}</Link></h5>
<p className="text-muted mb-0">{user.designation}</p>
</td>
</tr>
)
}
</tbody>
</Table>
</div>
</Col>
<Col className="col-lg-6">
{/* fullcalendar control */}
<FullCalendar ref={calendarComponentRef} defaultView="dayGridMonth" plugins={[BootstrapTheme, dayGridPlugin, interactionPlugin]}
slotDuration={'00:15:00'}
minTime={'08:00:00'}
maxTime={'19:00:00'}
handleWindowResize={true}
themeSystem="bootstrap"
header={{
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,dayGridWeek,dayGridDay'
}}
events={calendarEvents}
editable={true}
droppable={true}
eventLimit={true}
selectable={true}
dateClick={handleDateClick}
eventClick={handleEventClick}
drop={onDrop}
id="calendar" />
<button onClick={() => togglecategory() }
className="btn btn-secondary float-right btn-lg waves-effect btn btn-secondary">
Neuen Termin anlegen
</button>
{/* New event modal */}
<Modal isOpen={modal} toggle={() => toggle()} className="">
<ModalHeader toggle={() => toggle()} tag="h4">
Add Event
</ModalHeader>
<ModalBody>
<AvForm onValidSubmit={handleValidEventSubmit}>
<Row form>
<Col className="col-12">
<AvField name="title" label="Event Name" type="text" errorMessage="Invalid name" validate={{
required: { value: true }
}} value={event ? event.title : ''} />
</Col>
<Col className="col-12">
<AvField type="select" name="category" label="Select Category"
value={event ? event.category : 'bg-primary'}>
<option value="bg-danger">Danger</option>
<option value="bg-success">Success</option>
<option value="bg-primary">Primary</option>
<option value="bg-info">Info</option>
<option value="bg-dark">Dark</option>
<option value="bg-warning">Warning</option>
</AvField>
</Col>
</Row>
<Row>
<Col>
<div className="text-right">
<button type="button" className="btn btn-light mr-2" onClick={() => toggle()}>Close</button>
<button type="submit" className="btn btn-success save-event">Save</button>
</div>
</Col>
</Row>
</AvForm>
</ModalBody>
</Modal>
{/* edit event modal */}
<Modal isOpen={modal1} toggle={() => toggle1()} className="">
<ModalHeader toggle={() => toggle1()} tag="h4">
Edit Event
</ModalHeader>
<ModalBody>
<AvForm onValidSubmit={handleValidEventSubmitEvent}>
<Row form>
<Col className="col-12">
<AvField name="title" label="Event Name" type="text" errorMessage="Invalid name" validate={{
required: { value: true }
}} value={event ? event.title : ''} />
</Col>
<Col className="col-12">
<AvField type="select" name="category" label="Select Category"
value={event ? event.category : 'bg-primary'}>
<option value="bg-danger">Danger</option>
<option value="bg-success">Success</option>
<option value="bg-primary">Primary</option>
<option value="bg-info">Info</option>
<option value="bg-dark">Dark</option>
<option value="bg-warning">Warning</option>
</AvField>
</Col>
</Row>
<Row>
<Col>
<div className="text-right">
<button type="button" className="btn btn-light mr-2" onClick={() => toggle()}>Close</button>
<button type="submit" className="btn btn-success save-event">Save</button>
</div>
</Col>
</Row>
</AvForm>
</ModalBody>
</Modal>
<Modal isOpen={modalcategory} toggle={() => togglecategory()} className="">
<ModalHeader toggle={() => togglecategory()} tag="h4">
Add a category
</ModalHeader>
<ModalBody>
<AvForm onValidSubmit={handleValidEventSubmitcategory}>
<Row form>
<Col className="col-12">
<AvField name="title_category" label="Category Name" type="text" errorMessage="Invalid name" validate={{
required: { value: true }
}} value={title_category ? event.title_category : ''} />
</Col>
<Col className="col-12">
<AvField type="select" name="event_category" label="Choose Category Color"
value={event ? event.event_category : 'bg-primary'}>
<option value="bg-danger">Danger</option>
<option value="bg-success">Success</option>
<option value="bg-primary">Primary</option>
<option value="bg-info">Info</option>
<option value="bg-dark">Dark</option>
<option value="bg-warning">Warning</option>
</AvField>
</Col>
</Row>
<Row>
<Col>
<div className="text-right">
<button type="button" className="btn btn-light mr-2" onClick={() => togglecategory()}>Close</button>
<button type="submit" className="btn btn-success save-event">Save</button>
</div>
</Col>
</Row>
</AvForm>
</ModalBody>
</Modal>
</Col>
</Row>
</CardBody>
</Card>
</Container>
</div>
</React.Fragment>
);
}
export default ContactsList;
任何提示或帮助将不胜感激 - 提前致谢!
几件事:
- 您不应在函数本身中获取数据 - 这将在每次组件呈现时触发获取。通常,您希望在组件首次呈现时开始获取:
useEffect(() => {
fetchData().then(response => {
const employees = JSON.parse(response)
setEmployees(employees)
})
}, [])
另见这个问题:
现在我们有了正确的方法来获取数据,我们开始讨论另一个问题 - what to set the state to by definition
。也就是说,如何初始化数据。人们可能会告诉你它可以是任何东西,但实际上,如果你正在使用一个数组(你正在迭代 employees 对象,所以我假设它是一个数组),最好用一个空数组初始化它.这样类型就不会改变,下面的 JSX 不需要额外的条件逻辑来处理不同类型的员工。
const [employees, setEmployees] = useState([])
我通常先调用useState,然后再调用useEffect。实际上,如果你交换它们,不确定它是否会破裂。所以总代码为:
const fetchData = async () => {
const res = await fetch('https://swapi.dev/api/people/')
const json = await res.json()
return json.result
}
const ContactsList = props => {
const [employees, setEmployees] = useState([])
useEffect(() => {
fetchData().then(employees => {
setEmployees(employees)
})
}, [])
return (
<div>
{employees.map(employee => <div key={employee.id}>{employee.name}</div>)}
</div>
)
}
更笼统的说明:
- 你的组件很大。 React 的美妙之处在于你可以将它分成子组件。这不仅对您自己是个好习惯,而且其他 Whosebug 用户也更容易理解您的问题。只在组件中保留真正需要的东西。