I am trying to call Apollo Mutation Hook on form submit to create a new record in the database.
export default function NewJobForm() {
const { loading, error, data } = useQuery(GET_LOC_CAT_TYPE_QUERY);
const [newJob] = useMutation(NEW_JOB_MUTATION);
const [remote, setRemote] = useState(false);
const editorRef = useRef(null);
const log = () => {
if (editorRef.current) {
console.log(editorRef.current.getContent());
}
};
let initialFormValues = {
companyName: '',
title: '',
};
const JobSchema = yup.object({
companyName: yup.string().required('Please enter the company name.'),
title: yup.string().required('Please enter the job title.'),
});
let formValidate = (values) => {
console.log(values);
const errors = {};
return errors;
};
let handleError = (field, actions) => {
field.forEach((data) => {
let field = data.param;
switch (field) {
// case 'name':
// actions.setFieldError('name', data.msg);
// break;
default:
break;
}
});
};
let formSubmit = async (values, actions) => {
console.log(values);
newJob({ variables: values });
};
return (
<>
<Formik
validationSchema={JobSchema}
validate={(values) => formValidate(values)}
onSubmit={(values, actions) => formSubmit(values, actions)}
enableReinitialize={true}
initialValues={initialFormValues}
validateOnChange={true}
validateOnBlur={false}
>
{({ handleSubmit, setFieldValue, values }) => (
<form noValidate onSubmit={handleSubmit}>
<div className="space-y-8 divide-y divide-gray-200">
<div>
<div>
<h3 className="text-lg font-medium leading-6 text-gray-900">
Job Details
</h3>
<p className="mt-1 text-sm text-gray-500">
This information will be displayed
publicly so be careful what you share.
</p>
</div>
<div className="grid grid-cols-1 mt-6 gap-y-6 gap-x-4 sm:grid-cols-6">
<div className="sm:col-span-4">
<TextInput
label="Company Name"
id="companyName"
name="companyName"
type="text"
placeholder="eg: Google"
helpText="Please Enter the name of the company"
/>
</div>
<div className="sm:col-span-4">
<TextInput
label="Job Title"
id="title"
name="title"
type="text"
/>
</div>
</div>
</div>
</div>
</form>
)}
</Formik>
</>
);
}
On Form Submit the console.log displays the message but the mutation network call does not seem to get triggered.
I want to display the Child component on click on Button, But here I am getting the Data when the page loads,I need to write a condition like when Button Clicked , then only the Child component show display otherwise a default text should display there.
const DetailsCard = () => {
const [employee, setemployee] = useState([])
const [data, setData] = useState()
useEffect(() => {
fetch("http://localhost:3000/users").then(res => res.json()).then((result) => {
setemployee(result);
}, [])
})
const handleChange = () => {
setData(true);
}
return (
<div>
<h1>LordShiva</h1>
<div className="container">
<div className="row">
<div className="col">
<div className="card">
<div className="card-header bg-primary text-white">
<p className="h4">Birthday APP</p>
<button className="btn btn-red true1 " onClick={handleChange} >HappyBirthday</button>
</div>
<div className="card-body">
<TableCard data={employee} />
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default DetailsCard;
const DetailsCard = () => {
const [employee, setemployee] = useState([]);
const [showChild, toggleShowChild] = useState(false);
useEffect(() => {
fetch("http://localhost:3000/users")
.then((res) => res.json())
.then((result) => {
setemployee(result);
}, []);
});
const handleChange = () => {
toggleShowChild(!showChild);
};
return (
<div>
<h1>LordShiva</h1>
<div className="container">
<div className="row">
<div className="col">
<div className="card">
<div className="card-header bg-primary text-white">
<p className="h4">Birthday APP</p>
<button className="btn btn-red true1 " onClick={handleChange}>
HappyBirthday
</button>
</div>
{/* Only show child when `showChild` is true. */}
{showChild && (
<div className="card-body">
<TableCard data={employee} />
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
};
export default DetailsCard;
Codesandbox
import React, { useState, useEffect } from "react";
const FetchAPI = () => {
const [data, setData] = useState([]);
const newData = data.slice(0, 12);
const [showData, setShowData] = useState(false);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((response) => response.json())
// .then((json) => console.log(json));
.then((json) => setData(json));
}, []);
const onClickhandler = () => {
setShowData(!showData);
};
return (
<>
<h1>Search</h1>
<ul>
{newData.map((item) => {
return showData ? (
<li style={{ listStyle: "none", marginTop: "10px" }} key={item.id}>
{item.title}
</li>
) : (
""
);
})}
</ul>
<button onClick = {onClickhandler}>
Fetch
</button>
</>
);
};
export default FetchAPI;
when I reload browser I can see the post's pics
I have a component referring to the posts, but when you make a post that contains images, they are not updated and the post remains with the images from the previous post, the only way to prevent this from happening is by updating the browser and it should not be like that
Could someone help me to know what is happening, if I should update the component when loading the images or what should I do?
Thanks!
fomPost.vue =>
<template>
<div class="card bg-dark border-left-primary border-right-primary shd mb-4">
<div class="card-body">
<div v-if="status_msg" :class="{ 'alert-green': status, 'alert-danger': !status }" class="alert"
role="alert">{{ status_msg }}
</div>
<div class="form-group">
<textarea id="content-body" class="form-control" v-model="body"></textarea>
<a href="javascript:void(0)" class="text-lg float-right" data-toggle="tooltip"
data-title="Agregar imágenes" data-placement="bottom" #click="toggle()">
<i class="fas fa-cloud-upload-alt"></i>
</a>
</div>
<div v-show="isOpen" :style="'margin-top: 2rem'">
<div class="uploader"
#dragenter="OnDragEnter"
#dragleave="OnDragLeave"
#dragover.prevent
#drop="onDrop"
:class="{ dragging: isDragging }">
<div class="upload-control" v-show="images.length">
<label for="file">Agregar más imágenes</label>
</div>
<div v-show="!images.length">
<p>Arrastra las imágenes ó</p>
<div class="file-input">
<label for="file">Selecciónalas</label>
<input type="file" id="file" #change="onInputChange"
accept="image/x-png,image/gif,image/jpeg" multiple>
</div>
</div>
</div>
<div class="images-preview" v-show="images.length">
<div class="img-wrapper" v-for="(image, index) in images" :key="index">
<div class="thumbnail" :style="`background-image: url(${image.replace(/(\r\n|\n|\r)/gm)})`">
<div class="options">
<div>
<a href="javascript:void(0)" class="text-light" uk-tooltip="title: Eliminar"
#click="removeimage(index)">
<i class="fas fa-trash-alt"></i>
</a>
</div>
<div>
<a href="javascript:void(0)" class="text-light" uk-tooltip="title: Previsualizar"
uk-toggle="target: #modal-media-image" #click="showImage(image)">
<i class="fas fa-search-plus"></i>
</a>
</div>
</div>
</div>
<div class="details">
<span class="size" v-text="getFileSize(files[index].size)"></span>
</div>
<div id="modal-media-image" class="uk-flex-top" uk-modal>
<div class="uk-modal-dialog uk-width-auto uk-margin-auto-vertical">
<button class="uk-modal-close-outside" type="button" uk-close></button>
<img width="1024px" :src="dialogImageUrl">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer bg-opacity-7-dark">
<button type="button" #click="createPost" class="btn btn-primary float-right">
<template v-if="isCreatingPost" class="align-items-center">
<div class="d-flex align-items-center">
<span class="mr-1">Publicando</span>
<div class="loadingio-spinner-dual-ring-botj7pu8xqc">
<div class="ldio-ifliw7yncz">
<div></div>
<div>
<div></div>
</div>
</div>
</div>
</div>
</template>
<template v-else>
Publicar
</template>
</button>
</div>
</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
name: "FormPostText",
props: ['profile'],
data() {
return {
dialogImageUrl: "",
dialogVisible: false,
isDragging: false,
dragCount: 0,
files: [],
images: [],
status_msg: "",
status: "",
isCreatingPost: false,
title: "",
body: "",
isOpen: false
}
},
mounted() {
$("#content-body").emojioneArea({
placeholder: "¿Qué estás pensando?",
searchPlaceholder: "Buscar",
buttonTitle: "Usa la tecla [TAB] para insertarlos más rápido",
pickerPosition: 'bottom',
filtersPosition: "bottom",
searchPosition: "top"
});
},
methods: {
...mapActions({
create: "post/makePost"
}),
showImage(file) {
this.dialogImageUrl = file;
this.dialogVisible = true;
},
OnDragEnter(e) {
e.preventDefault();
this.dragCount++;
this.isDragging = true;
return false;
},
OnDragLeave(e) {
e.preventDefault();
this.dragCount--;
if (this.dragCount <= 0)
this.isDragging = false;
},
onInputChange(e) {
const files = e.target.files;
Array.from(files).forEach(file => this.addImage(file));
},
onDrop(e) {
e.preventDefault();
e.stopPropagation();
this.isDragging = false;
const files = e.dataTransfer.files;
Array.from(files).forEach(file => this.addImage(file));
},
addImage(file) {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.showNotification("La imágen no puede ser mayor a 2MB.");
return;
}
if (!file.type.match('image.*')) {
this.showNotification(`${file.name} no es una imágen`);
return;
}
this.files.push(file);
const img = new Image(), reader = new FileReader();
reader.onload = (e) => this.images.push(e.target.result);
reader.readAsDataURL(file);
return isLt2M;
},
removeimage: function (index) {
this.images.splice(index, 1);
},
getFileSize(size) {
const fSExt = ['Bytes', 'KB', 'MB', 'GB'];
let i = 0;
while (size > 900) {
size /= 1024;
i++;
}
return `${(Math.round(size * 100) / 100)} ${fSExt[i]}`;
},
toggle() {
this.isOpen = !this.isOpen;
},
createPost() {
var body = $("#content-body").val();
var text = emojione.toImage(body);
if (!this.validateForm()) {
return false;
}
this.isCreatingPost = true;
const formData = new FormData();
formData.append("user", this.profile.uid);
formData.append("body", text);
this.files.forEach(file => {
formData.append('images[]', file, file.name);
});
this.create(formData).then((res) => {
if (res.data.status === 0) {
this.status = code;
this.showNotification(res.data.msg);
}
document.querySelector(".emojionearea-editor").innerHTML = '';
this.isCreatingPost = false;
this.images = [];
this.files = [];
this.isOpen = false;
let post = res.data;
this.$emit("new", post);
}).catch(error => {
console.log(error)
this.isCreatingPost = false;
});
},
validateForm() {
if (!$("#content-body").val()) {
this.status = false;
this.showNotification("Debes escribir algo para publicar...");
return false;
}
return true;
},
showNotification(message) {
this.$swal.fire({
icon: 'error',
html: message
});
}
}
}
</script>
Post.vue =>
<template>
<div id="timeline">
<div v-if="authenticated.username === username || isFriend">
<FormPost :profile="profile" #new="addPostText"></FormPost>
</div>
<!--<pre>{{postsArr}}</pre>-->
<div v-if="postsCount > 0">
<div v-for="(post, index) in postsArr" :key="index">
<div class="cardbox shadow-lg bg-opacity-5-dark shd">
<div class="cardbox-heading">
<div class="dropdown float-right">
<button class="btn btn-sm btn-dark btn-circle" data-toggle="dropdown"
data-boundary="window">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu dropdown-scale dropdown-menu-right" role="dropdown">
<template v-if="post.user.id === user.uid || post.friend.id === user.uid">
<b-dropdown-item href="javascript:void(0)" #click="deletePost(post.post.id, index)">
<span class="uk-margin-small-right" uk-icon="icon: trash"></span> Eliminar
</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
</template>
<b-dropdown-item href="javascript:void(0)">
<span class="uk-margin-small-right text-danger" uk-icon="icon: warning"></span>
Reportar
</b-dropdown-item>
</div>
</div>
<div class="media m-0">
<div class="d-flex mr-3">
<a v-bind:href="post.user.username">
<img class="img-fluid rounded-circle" v-bind:src="post.friend.photo" alt="User">
</a>
</div>
<div class="media-body">
<p class="m-0"><a v-bind:href="post.friend.username">{{ '#' + post.friend.username }}</a></p>
<small><span><i
class="far fa-clock"></i> {{ since(post.post.created_at) }}</span></small>
</div>
</div>
</div>
<div class="cardbox-item">
<p class="mx-4">{{ post.post.body | setEmoji }}</p>
<div v-if="post.images.length > 0">
<!--<photo-grid
:box-height="'600px'"
:box-width="'100%'"
:boxBorder="0"
:excess-text="'+ {{count}} imágenes'"
uk-lightbox="animation: slide"
>
<img v-for="(imahe, index) in post.images" v-bind:src="`http://127.0.0.1:8000/storage/images/${post.friend.id}/${imahe.url}`" :key="index"/>
</photo-grid>-->
<ImagesGrid :images="post.images" :idFriend="post.friend.id"
uk-lightbox="animation: slide"></ImagesGrid>
</div>
</div>
<div class="cardbox-base">
<ul class="float-right">
<li><a><i class="fa fa-comments"></i></a></li>
<li><a><em class="mr-5">{{ post.comments_count || comments_count }}</em></a></li>
<li><a><i class="fa fa-share-alt"></i></a></li>
<li><a><em class="mr-3">03</em></a></li>
</ul>
<ul>
<li>
<Likes :postid="post.post.id" :user="user"></Likes>
</li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/3.jpeg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/1.jpg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/5.jpg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a href="#"><img
src="http://www.themashabrand.com/templates/bootsnipp/post/assets/img/users/2.jpg"
class="img-fluid rounded-circle" alt="User"></a></li>
<li><a><span>242 Likes</span></a></li>
</ul>
</div>
<CommentsPost
#new="commentsCount"
:postid="post.post.id"
:postuserid="user.uid"
:user="user"
></CommentsPost>
</div>
</div>
<nav class="pagination-outer">
<ul class="pagination">
<li class="page-item" :class="[pagination.current_page > 1 ? '' : 'disabled']">
<a href="#" class="page-link" aria-label="Previous" #click.prevent="changePage(pagination.current_page - 1)">
<span aria-hidden="true">«</span>
</a>
</li>
<li class="page-item" v-for="page in pagesNumber" :class="[page == isActived ? 'active' : '']">
<a class="page-link" href="#" v-bind:data-hover="page" #click.prevent="changePage(page)">{{page}}</a>
</li>
<li class="page-item" :class="[pagination.current_page < pagination.last_page ? '' : 'disabled']">
<a href="#" class="page-link" aria-label="Next" #click.prevent="changePage(pagination.current_page + 1)">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<div v-else class="card bg-opacity-5-dark mb-4">
<div class="card-body">
<span class="text-light">No tiene posts aún.</span>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
var moment = require("moment");
moment.locale("es");
import {mapActions, mapGetters} from 'vuex'
import FormPost from "../Posts/FormPost";
import Likes from "../Posts/Likes";
import CommentsPost from "../Posts/CommentsPost";
import ImagesGrid from "../Posts/ImagesGrid";
export default {
name: "Posts",
props: {
username: {
type: String,
required: true
},
profile: {
type: Object,
required: true
},
user: {
type: Object,
required: true
},
isFriend: {
type: Boolean,
required: true
}
},
data() {
return {
page: 0,
offset: 4,
comments_count: ''
}
},
mounted() {
this.getPosts();
},
beforeRouteEnter(to, from, next) {
this.getPosts()
next()
},
beforeRouteUpdate(to, from, next) {
this.getPosts()
next()
},
computed: {
...mapGetters({
authenticated: "auth/authenticated",
postsArr: "post/postsLists",
pagination: "post/postsPagination",
postsCount: "post/postsCount"
}),
isActived: function() {
return this.pagination.current_page;
},
pagesNumber: function () {
if(!this.pagination.to) {
return [];
}
var from = this.pagination.current_page - this.offset;
if(from < 1) {
from = 1;
}
var to = from + (this.offset * 2);
if(to >= this.pagination.last_page) {
to = this.pagination.last_page;
}
var pagesArray = [];
while(from <= to) {
pagesArray.push(from);
from++;
}
return pagesArray;
}
},
methods: {
...mapActions({
getPostsByUser: "post/fetchPosts",
removePost: "post/deletePost",
}),
async getPosts(page) {
await this.getPostsByUser(page);
await this.$forceUpdate();
},
async addPostText(post) {
await this.postsArr.unshift(post);
await this.$forceUpdate();
await this.changePage(1);
},
since(d) {
return moment(d).fromNow();
},
commentsCount(count) {
this.comments_count = count;
},
deletePost(post, index) {
this.postsArr.splice(index, 1)
this.removePost(post)
},
changePage(page) {
this.pagination.current_page = page;
this.getPosts(page);
}
},
filters: {
setEmoji: (value) => {
var rx = /<img\s+(?=(?:[^>]*?\s)?class="[^">]*emojione)(?:[^>]*?\s)?alt="([^"]*)"[^>]*>(?:[^<]*<\/img>)?/gi;
return value.replace(rx, "$1")
}
},
components: {
FormPost,
Likes,
CommentsPost,
ImagesGrid
},
watch: {
'$route': 'getPosts'
}
ImagesGrid.vue =>
<template>
<photo-grid
:box-height="'600px'"
:box-width="'100%'"
:boxBorder="0"
:excess-text="'+ {{count}} imágenes'"
uk-lightbox="animation: slide"
>
<a :href="`http://127.0.0.1:8000/storage/images/${idFriend}/${imahe.url}`"
v-for="(imahe, index) in images"
v-bind:data-image="`http://127.0.0.1:8000/storage/images/${idFriend}/${imahe.url}`"
:key="index">
</a>
</photo-grid>
</template>
<script>
export default {
props: ['idFriend', 'images'],
watch: {
$route(to, from, next) {
this.$forceUpdate();
next()
}
}
};
</script>
Post.js =>
import axios from 'axios'
import store from './index'
export default {
namespaced: true,
state: {
posts: [],
posts_count : 0,
pagination: {
'total': 0,
'current_page': 0,
'per_page': 0,
'last_page': 0,
'from': 0,
'to': 0,
}
},
getters: {
postsLists(state) {
return state.posts;
},
postsCount(state) {
return state.posts_count
},
postsPagination(state) {
return state.pagination
}
},
mutations: {
SET_POST_COLLECTION (state, data) {
state.posts = data.posts.data ;
state.pagination = data.paginate;
state.posts_count = data.paginate.total;
}
},
actions: {
makePost({commit,dispatch}, data) {
return new Promise((resolve, reject) => {
axios.post('user/post/create', data)
.then((response) => {
dispatch("fetchPosts", 1)
resolve(response);
})
.catch((error) => {
reject(error);
});
})
},
fetchPosts({commit}, page) {
return new Promise((resolve, reject) => {
axios.get(`user/${store.state.user.profile.username}/posts?page=${page}`)
.then((response) => {
//console.log(response.data.posts.data);
commit('SET_POST_COLLECTION', response.data);
resolve(response);
})
.catch((error) => {
reject(error);
});
})
},
deletePost({commit}, id) {
return new Promise((resolve, reject) => {
let params = {'id': id};
axios.post('user/post/delete', params)
.then((response) => {
console.log(response.data)
resolve(response);
})
.catch((error) => {
reject(error);
});
})
},
createComment({commit}, comment) {
return new Promise((resolve, reject) => {
axios.post('user/post/comment/create', comment)
.then((response) => {
console.log(response.data)
resolve(response);
})
.catch((error) => {
reject(error);
});
})
}
}
}
I m developing an e-commerce application with react hooks in search component result is shown beneath the component I want to render on search Result component how to redirect search result on the search Result component
import React, { useState, useEffect } from "react";
import { Link, Redirect } from "react-router-dom";
import { getCategories, list } from "./apiCore";
import SearchResult from "./SearchResult";
const Search = () => {
const [data, setData] = useState({
categories: [],
category: "",
search: "",
results: [],
searched: false,
});
const { categories, category, search, results, searched } = data;
const loadCategories = () => {
getCategories().then(data => {
if (data.error) {
console.log(data.error);
} else {
setData({ ...data, categories: data });
}
});
};
useEffect(() => {
loadCategories();
}, []);
const searchData = () => {
// console.log(search, category);
if (search) {
list({ search: search || undefined, category: category }).then(
response => {
if (response.error) {
console.log(response.error);
} else {
setData({ ...data, results: response, searched: true });
}
}
);
}
};
const searchSubmit = e => {
e.preventDefault();
searchData();
};
const handleChange = name => event => {
setData({ ...data, [name]: event.target.value, searched: false });
};
const searchMessage = (searched, results) => {
if (searched && results.length > 0) {
return `Found ${results.length} products`;
}
if (searched && results.length < 1) {
return `No products found`;
}
};
const searchedProducts = (results = []) => {
return (
<div>
<h2 className="text-muted mb-4">
{searchMessage(searched, results)}
</h2>
<div className="row">
{results.map((product, i) => (
<CarouselCard key={i} product={product} />
))}
</div>
</div>
);
};
return (
<div className="site-navbar-top">
<div className="container">
<div className="row align-items-center">
<div className="col-6 col-md-4 order-2 order-md-1 site-search-icon text-left">
<form className="site-block-top-search" onSubmit={searchSubmit}>
<span className="icon icon-search2"></span>
<input type="text" className="form-control border-0" placeholder="Search" onChange={handleChange("search")} />
</form>
</div>
<div className="col-12 mb-3 mb-md-0 col-md-4 order-1 order-md-2 text-center">
<div className="site-logo">
<Link to="/" className="js-logo-clone">Shoppers</Link>
</div>
</div>
<div className="col-6 col-md-4 order-3 order-md-3 text-right">
<div className="site-top-icons">
<ul>
<li><Link to="#"><span className="icon icon-person" /></Link></li>
<li><Link to="#"><span className="icon icon-heart-o" /></Link></li>
<li>
<Link to="cart.html" className="site-cart">
<span className="icon icon-shopping_cart" />
<span className="count">2</span>
</Link>
</li>
</ul>
</div>
</div>
</div>
</div>
{searchedProducts(results)}
</div>
)
}
export default Search;
The main part of the hook is pretty straightforward, but I'm having a difficult time finding a nice way to handle that redirect. The current working solution is to wrap the functional component with withRouter, then pass props.history
I'm a begginer in React. I'm trying to fetch an array of data about orders and that is working and then map it to display specific information about each order.
I'm getting TypeError: orders.map is not a function exception in my application.
Here's my code:
class Orders extends Component {
state = {
orders: []
};
componentDidMount() {
axios
.get("https://localhost:9090/orders")
.then(res => {
this.setState({ orders: res.data });
console.log(res.data);
});
}
render() {
const { orders } = this.state;
const orderList =
this.state.orders.length > 0 ? (
orders.map(o => {
return (
<div key={o.orderId}>
<p>
{o.isbn}
</p>
</div>
);
})
) : (
<div className="row p-5 m-5">
<div className="offset-sm-5 col-sm-2 text-center">
<span className="text-grey r">Loading...</span>
</div>
</div>
);
return <div className="container">{orderList}</div>;
}}
What's interesting, I have a similar code, that is working. The only difference is basically what it's fetching. Here's the code:
class BookList extends Component {
state = {
books: []
};
componentDidMount() {
console.log(this.props.match.params.search_term);
axios
.get("https://localhost:8080/search?searchTerm=" + search_term)
.then(res => {
this.setState({ books: res.data });
console.log(res.data);
});
}
render() {
const { books } = this.state;
const booksList =
this.state.books.length > 0 ? (
books.map(b => {
return (
<div key={b.isbn} className="card">
<div className="card-body">
<h5 className="card-title">
<Link to={"/details/" + b.isbn}>{b.title}</Link>
</h5>
<div className="card-subtitle text-muted">
{b.author} ({b.year}) /{" "}
<span className=" text-danger">{b.category}</span>
</div>
<p />
</div>
</div>
);
})
) : (
<div className="row p-5 m-5">
<div className="offset-sm-5 col-sm-2 text-center">
<span className="text-grey r">Loading...</span>
</div>
</div>
);
return <div className="container">{booksList}</div>;
}}
I can't find the difference that would cause that exception. It is an array in both cases.
Any suggestions?
EDIT:
here's the output of response data:
response data of order
response data of bokstore
From them images it looks like the orders are processed as plain text and not parsed to JSON. Check that your back-end specifies the required headers Content-Type: application/json so that axios will parse the data correctly.
Alternatively you could parse the text client-side with JSON.parse(res.data)