#javascript #reactjs #api
#javascript #reactjs #API
Вопрос:
Я новичок в reactjs и был бы признателен за небольшую помощь здесь. Мой reactjs spa потребляет из Asp.Net Веб-Api. Когда я делаю запрос get через postman, он возвращает все свойства / информацию из базы данных. Но когда это делается с помощью моего приложения react, оно возвращает всего пару свойств, исключая остальные. Я вставлю ниже коды компонентов fetch wrapper, @service и page.
Извлекать оболочку
import config from 'config';
import { healthcareProviderService } from '@/_services';
export const fetchWrapperHealthcareProvider = {
get,
post,
put,
delete: _delete
}
function get(url) {
const requestOptions = {
method: 'GET',
headers: authHeader(url)
};
return fetch(url, requestOptions).then(handleResponse);
}
function post(url, body) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...authHeader(url) },
credentials: 'include',
body: JSON.stringify(body)
};
return fetch(url, requestOptions).then(handleResponse);
}
function put(url, body) {
const requestOptions = {
method: 'PUT',
headers: { 'Content-Type': 'application/json', ...authHeader(url) },
body: JSON.stringify(body)
};
return fetch(url, requestOptions).then(handleResponse);
}
// prefixed with underscored because delete is a reserved word in javascript
function _delete(url) {
const requestOptions = {
method: 'DELETE',
headers: authHeader(url)
};
return fetch(url, requestOptions).then(handleResponse);
}
// helper functions
function authHeader(url) {
// return auth header with jwt if user is logged in and request is to the api url
const user = healthcareProviderService.userValue;
const isLoggedIn = user amp;amp; user.jwtToken;
const isApiUrl = url.startsWith(config.apiUrl);
if (isLoggedIn amp;amp; isApiUrl) {
return { Authorization: `Bearer ${user.jwtToken}` };
} else {
return {};
}
}
function handleResponse(response) {
return response.json().then(text => {
const data = text amp;amp; JSON.parse(text);
if (!response.ok) {
if ([401, 403].includes(response.status) amp;amp; healthcareProviderService.userValue) {
// auto logout if 401 Unauthorized or 403 Forbidden response returned from api
healthcareProviderService.logout();
}
const error = (data amp;amp; data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
}
healthProviderService от @service
import { BehaviorSubject } from 'rxjs';
import config from 'config';
import { fetchWrapperHealthcareProvider, history } from '@/_helpers';
const userSubject = new BehaviorSubject(null);
const baseUrl = `${config.apiUrl}/healthcareprovider`;
export const healthcareProviderService = {
login,
logout,
refreshToken,
register,
verifyEmail,
forgotPassword,
validateResetToken,
resetPassword,
getAll,
getById,
create,
update,
delete: _delete,
user: userSubject.asObservable(),
get userValue () { return userSubject.value }
};
function login(email, password) {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/authenticate`, { email, password })
.then(user => {
// publish user to subscribers and start timer to refresh token
userSubject.next(user);
startRefreshTokenTimer();
return user;
});
}
function logout() {
// revoke token, stop refresh timer, publish null to user subscribers and redirect to login page
fetchWrapperHealthcareProvider.post(`${baseUrl}/revoke-token`, {});
stopRefreshTokenTimer();
userSubject.next(null);
history.push('/account/login');
}
function refreshToken() {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/refresh-token`, {})
.then(user => {
// publish user to subscribers and start timer to refresh token
userSubject.next(user);
startRefreshTokenTimer();
return user;
});
}
function register(params) {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/register`, params);
}
function verifyEmail(token) {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/verify-email`, { token });
}
function forgotPassword(email) {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/forgot-password`, { email });
}
function validateResetToken(token) {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/validate-reset-token`, { token });
}
function resetPassword({ token, password, confirmPassword }) {
return fetchWrapperHealthcareProvider.post(`${baseUrl}/reset-password`, { token, password, confirmPassword });
}
function getAll() {
return fetchWrapperHealthcareProvider.get(baseUrl);
}
function getById(id) {
return fetchWrapperHealthcareProvider.get(`${baseUrl}/${id}`);
}
function create(params) {
return fetchWrapperHealthcareProvider.post(baseUrl, params);
}
function update(id, params) {
return fetchWrapperHealthcareProvider.put(`${baseUrl}/${id}`, params)
.then(user => {
// update stored user if the logged in user updated their own record
if (user.id === userSubject.value.id) {
// publish updated user to subscribers
user = { ...userSubject.value, ...user };
userSubject.next(user);
}
return user;
});
}
// prefixed with underscore because 'delete' is a reserved word in javascript
function _delete(id) {
return fetchWrapperHealthcareProvider.delete(`${baseUrl}/${id}`)
.then(x => {
// auto logout if the logged in user deleted their own record
if (id === userSubject.value.id) {
logout();
}
return x;
});
}
// helper functions
let refreshTokenTimeout;
function startRefreshTokenTimer() {
// parse json object from base64 encoded jwt token
const jwtToken = JSON.parse(atob(userSubject.value.jwtToken.split('.')[1]));
// set a timeout to refresh the token a minute before it expires
const expires = new Date(jwtToken.exp * 1000);
const timeout = expires.getTime() - Date.now() - (60 * 1000);
refreshTokenTimeout = setTimeout(refreshToken, timeout);
}
function stopRefreshTokenTimer() {
clearTimeout(refreshTokenTimeout);
}
Обновить компонент страницы
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { Formik, Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';
import { healthcareProviderService, alertService } from '@/_services';
function Update({ history }) {
const user = healthcareProviderService.userValue;
const initialValues = {
fullName: user.fullName,
email: user.email,
role: user.role,
street: user.street,
city: user.city,
state: user.state,
zipCode: user.zipCode,
password: '',
confirmPassword: ''
};
const validationSchema = Yup.object().shape({
fullName: Yup.string()
.required('Name is required'),
email: Yup.string()
.email('Email is invalid')
.required('Email is required'),
role: Yup.string()
.required('Role is required'),
street: Yup.string()
.required('Street is required'),
city: Yup.string()
.required('City is required'),
state: Yup.string()
.required('State is required'),
zipCode: Yup.string()
.required('ZipCode is required'),
password: Yup.string()
.min(6, 'Password must be at least 6 characters'),
confirmPassword: Yup.string()
.when('password', (password, schema) => {
if (password) return schema.required('Confirm Password is required');
})
.oneOf([Yup.ref('password')], 'Passwords must match')
});
function onSubmit(fields, { setStatus, setSubmitting }) {
setStatus();
healthcareProviderService.update(user.id, fields)
.then(() => {
alertService.success('Update successful', { keepAfterRouteChange: true });
history.push('.');
})
.catch(error => {
setSubmitting(false);
alertService.error(error);
});
}
const [isDeleting, setIsDeleting] = useState(false);
function onDelete() {
if (confirm('Are you sure?')) {
setIsDeleting(true);
healthcareProviderService.delete(user.id)
.then(() => alertService.success('Account deleted successfully'));
}
}
return (
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={onSubmit}>
{({ errors, touched, isSubmitting }) => (
<Form>
<h1>Update Profile</h1>
<div className="form-row">
<div className="form-group col-4">
<label>Full Name</label>
<Field name="fullName" type="text" className={'form-control' (errors.fullName amp;amp; touched.fullName ? ' is-invalid' : '')} />
<ErrorMessage name="fullName" component="div" className="invalid-feedback" />
</div>
<div className="form-group col-4">
<label>Email</label>
<Field name="email" type="text" className={'form-control' (errors.email amp;amp; touched.email ? ' is-invalid' : '')} />
<ErrorMessage name="email" component="div" className="invalid-feedback" />
</div>
<div className="form-group col-4">
<label>Role</label>
<Field name="role" as="select" className={'form-control' (errors.role amp;amp; touched.role ? ' is-invalid' : '')}>
<option value=""></option>
<option value="HealthcareProvider">healthcareProvider</option>
</Field>
<ErrorMessage name="role" component="div" className="invalid-feedback" />
</div>
</div>
<div className="form-row">
<div className="form-group col-3">
<label>Street</label>
<Field name="street" type="text" className={'form-control' (errors.street amp;amp; touched.street ? ' is-invalid' : '')} />
<ErrorMessage name="street" component="div" className="invalid-feedback" />
</div>
<div className="form-group col-3">
<label>City</label>
<Field name="city" type="text" className={'form-control' (errors.city amp;amp; touched.city ? ' is-invalid' : '')} />
<ErrorMessage name="city" component="div" className="invalid-feedback" />
</div>
<div className="form-group col-3">
<label>State</label>
<Field name="state" type="text" className={'form-control' (errors.state amp;amp; touched.state ? ' is-invalid' : '')} />
<ErrorMessage name="state" component="div" className="invalid-feedback" />
</div>
<div className="form-group col-3">
<label>ZipCode</label>
<Field name="zipCode" type="text" className={'form-control' (errors.zipCode amp;amp; touched.zipCode ? ' is-invalid' : '')} />
<ErrorMessage name="zipCode" component="div" className="invalid-feedback" />
</div>
</div>
<h3 className="pt-3">Change Password</h3>
<p>Leave blank to keep the same password</p>
<div className="form-row">
<div className="form-group col">
<label>Password</label>
<Field name="password" type="password" className={'form-control' (errors.password amp;amp; touched.password ? ' is-invalid' : '')} />
<ErrorMessage name="password" component="div" className="invalid-feedback" />
</div>
<div className="form-group col">
<label>Confirm Password</label>
<Field name="confirmPassword" type="password" className={'form-control' (errors.confirmPassword amp;amp; touched.confirmPassword ? ' is-invalid' : '')} />
<ErrorMessage name="confirmPassword" component="div" className="invalid-feedback" />
</div>
</div>
<div className="form-group">
<button type="submit" disabled={isSubmitting} className="btn btn-primary mr-2">
{isSubmitting amp;amp; <span className="spinner-border spinner-border-sm mr-1"></span>}
Update
</button>
<button type="button" onClick={() => onDelete()} className="btn btn-danger" style={{ width: '75px' }} disabled={isDeleting}>
{isDeleting
? <span className="spinner-border spinner-border-sm"></span>
: <span>Delete</span>
}
</button>
<Link to="." className="btn btn-link">Cancel</Link>
</div>
</Form>
)}
</Formik>
)
}
export { Update };
Комментарии:
1. Пожалуйста, приведите пример того, какой метод вы фактически вызвали, и различия между postman и react app в выходных данных. (то есть укажите фактическое значение, пожалуйста)
Ответ №1:
Понял, что модель ответа на моем asp.net веб-api не был разработан для возврата отсутствующих свойств. Спасибо за вашу заботу.