如何解决从React Functional组件进行API调用
我是React的新手,我了解Functional和Class组件的概念以及诸如Hooks的钩子,例如useEffect和useState;因此,当我在下面的React组件上工作时,我很难将这些知识付诸实践。该组件可以进行简单的Javascript API调用,现在我想使用State和Hooks转换为“真正的” React API Call。>
我的问题如下:我想呈现API返回的雇员对象,从雇员的名字和姓氏开始,然后是其他信息。
使用纯Javascript对API的请求进行得很好,并返回了所需的数据;因此,我不确定如何根据定义将状态设置为什么(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,{ 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,name: "Mark Ellison",designation: "Full Stack Developer",email: "mark@skote.com",projects: "121",skills: [
{ name: "Ruby" },{ name: "Php" },{
id: 5,img: avatar4,name: "Minnie Walter",email: "minnie@skote.com",projects: "145",{
id: 6,img: avatar5,name: "Shirley Smith",email: "shirley@skote.com",projects: "136",{ name: "UI/UX Designer" }
]
},{
id: 7,name: "John Santiago",email: "john@skote.com",{
id: 8,img: avatar7,name: "Colin Melton",email: "colin@skote.com",];
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'
},title: 'My Event',type: 'info'
},title: 'Meet Manager',type: 'warning'
},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)
})
},[])
另请参阅以下问题:ReactJS: how to call useEffect hook only once to fetch API data
现在我们已经有了一种正确的数据获取方法,接下来我们要问另一个问题-what to set the state to by definition
。换句话说,如何初始化数据。人们可能会告诉您它可以是任何东西,但是实际上,如果您使用的是数组(您正在对employee对象进行迭代,那么我假设它是一个数组),那么最好使用一个空数组初始化它。这样,类型就不会改变,下面的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的优点在于您可以将其划分为子组件。这不仅对您自己是一个好习惯,而且对于其他StackOverflow用户来说也更容易理解您的问题。只保留真正需要的组件。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。