When trying to create new item in MERN stack, getting TypeError: this.props.meals.map is not a function - reactjs

I've created a MERN with redux application where users can order a meal from a menu. In the admin side, I am providing delete and add functions so the meals on the menu can be changed all in the same page. I have managed to get the delete meal item to work, but I am getting the following error when I try and add a new meal item:
My redux action is as follows:
export const createMeal = (meal) => (dispatch) => {
fetch("api/meals", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(meal),
})
.then((res) => res.json())
.then((data) => {
dispatch({ type: CREATE_MEAL, payload: data });
});
};
In my server file, I have the following endpoint created in Express:
app.post("/api/meals", async (req, res) => {
if (!req.body.title) {
return res.send({ message: "Data is required." });
}
const newMeal = new Meal(req.body);
const savedMeal = await newMeal.save();
res.send(savedMeal);
});
My UpdateMenuScreen is as follows:
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchMeals, deleteMeal, createMeal } from "../actions/mealActions";
class UpdateMenuScreen extends Component {
constructor(props) {
super(props);
this.state = {
meal: null,
showAddMenu: false,
title: "",
};
}
componentDidMount() {
this.props.fetchMeals();
}
componentDidUpdate() {
this.props.fetchMeals();
}
handleInput = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
createMeal = (e) => {
e.preventDefault();
const meal = {
title: this.state.title,
};
this.props.createMeal(meal);
};
deleteMeal(id) {
this.props.deleteMeal(id);
}
render() {
return (
<div>
<h3>Current Menu</h3>
{!this.props.meals ? (
<div>Loading...</div>
) : (
<ul className="meals">
{this.props.meals.map((meal) => (
<li key={meal._id}>
<div className="meal">
<p>{meal.title}</p>
<button
className="button"
onClick={() => this.props.deleteMeal(meal._id)}
>
Delete
</button>
</div>
</li>
))}
</ul>
)}
<button
onClick={() => {
this.setState({ showAddMenu: true });
}}
>
Add New Menu Item
</button>
{this.state.showAddMenu && (
<div className="cart">
<form onSubmit={this.createMeal}>
<ul className="form-container">
<li>
<label>Menu Item Title:</label>
<input
name="title"
type="text"
required
onChange={this.handleInput}
></input>
</li>
<li>
<button className="button primary" type="submit">
Save New Menu Item
</button>
</li>
</ul>
</form>
</div>
)}
</div>
);
}
}
export default connect((state) => ({ meals: state.meals.items }), {
fetchMeals,
deleteMeal,
createMeal,
})(UpdateMenuScreen);
Can anyone see what I'm missing? Or is it not possible to do this all on the same page?
EDIT:
I've console logged this.props.meals in ComponentDidMount and got the following results:
My mealsReducer is as follows:
const { FETCH_MEALS, DELETE_MEAL, CREATE_MEAL } = require("../types");
export const mealsReducer = (state = {}, action) => {
switch (action.type) {
case FETCH_MEALS:
return { items: action.payload };
case DELETE_MEAL:
return { items: action.payload };
case CREATE_MEAL:
return { items: action.payload };
default:
return state;
}
};
I also get this underneath my original error, could it be something in my mealActions that I don't have correct?

Please go to your reducer of meals and define the initial state of meals to []

This should fix your error.
render() {
const { meals = [] } = this.props // default to empty array when it's undefined
return (
<div>
<h3>Current Menu</h3>
{!meals.length ? (
<div>Loading...</div>
) : (
<ul className="meals">
{meals.map((meal) => (
<li key={meal._id}>
<div className="meal">
<p>{meal.title}</p>
<button
className="button"
onClick={() => this.props.deleteMeal(meal._id)}
>
Delete
</button>
</div>
</li>
))}
</ul>
)}
<button
onClick={() => {
this.setState({ showAddMenu: true });
}}
>
Add New Menu Item
</button>
{this.state.showAddMenu && (
<div className="cart">
<form onSubmit={this.createMeal}>
<ul className="form-container">
<li>
<label>Menu Item Title:</label>
<input
name="title"
type="text"
required
onChange={this.handleInput}
></input>
</li>
<li>
<button className="button primary" type="submit">
Save New Menu Item
</button>
</li>
</ul>
</form>
</div>
)}
</div>
);
}
}

Related

React API call is not working as intended with setState()

So here I'm fetching records by page. At mounting, I fetched page 1 and on next and prev button I'm changing the count, which is changing the page number and making a get request. But my code is not working correctly. It is giving me the result of count's previous state.
App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {},
count: 1,
};
}
handleApi = () => {
fetch(`http://localhost:9000/accounts?page=${this.state.count}`)
.then((res) => res.json())
.then((res) => {
this.setState({ data: res });
})
.catch((err) => console.log(err));
};
handlePrev = () => {
if (this.state.count > 1) {
this.setState((prevState) => ({
count: prevState.count - 1
}))
this.handleApi();
}
};
handleNext = () => {
if (this.state.count < this.state.data.total) {
this.setState((prevState) => ({
count: prevState.count + 1
}))
this.handleApi();
}
};
componentDidMount() {
this.handleApi();
}
render() {
return (
<div className="App container">
<h1 className="mb-3 text-center">Pagination Homepage</h1>
{Object.keys(this.state.data).length !== 0 ? (
<ListData detail={this.state.data} />
) : (
<h4 className="mb-5 text-center">No Data to Show.</h4>
)}
<nav aria-label="Page navigation example">
<ul className="pagination justify-content-center mt-4">
<li className="page-item">
<button
className="btn btn-outline-primary me-3"
onClick={this.handlePrev}
>
Prev
</button>
</li>
<li className="page-item">
<button
className="btn btn-outline-success"
onClick={this.handleNext}
>
Next
</button>
</li>
</ul>
</nav>
</div>
);
}
}
export default App;
ListData.js
export default class ListData extends Component {
render() {
return (
<div className="list-outer">
<h4 className="mb-3 text-center"> List Data</h4>
<div className="list-head">
<p>Name</p>
<p>E-mail</p>
</div>
{this.props.detail.data &&
this.props.detail.data.map((list, index) => (
<div key={list._id} className="list">
<p className="list-item">{list.name.toUpperCase()} </p>
<p className="list-item"> {list.mail}</p>
</div>
))}
</div>
);
}
}
Console
After updating the count the API is still calling count's previous state.
Here page number in Data should be equal to the count.
Since setState works in an asynchronous way, after calling setState the this.state variable is not immediately changed. So if you want to perform an action immediately after setting state on a state variable and then return a result, use a callback:
handlePrev = () => {
if (this.state.count > 1) {
this.setState((prevState) => ({
count: prevState.count - 1
}), () => this.handleApi());
}
};
handleNext = () => {
if (this.state.count < this.state.data.total) {
this.setState((prevState) => ({
count: prevState.count + 1
}), () => this.handleApi());
}
};

Todo App in React- Wanted to add button which when clicks deletes the whole todo list

I have created a ToDo App in React. I want to add a single button which when I clicked on removes the whole todo list and shows the message to the user "You don't have any todo's". I am trying to add functionality but can't seem to find a perfect way.
I have given all the Todos a unique id and I also to grab these id's but don't how to use them to remove all Todos from a single button only. Help me. Thanks in advance
here is my main component App.js
import React, { Component } from 'react';
import PrintTodo from "./printtodo"
import Addtodo from "./addTodo"
class App extends Component {
state = {
todos: [
{id:1, content:"Buy Tomatoes"},
]
}
deleteTodo = (id) => {
const todos = this.state.todos.filter(todo => {
return todo.id !== id
})
this.setState({
todos
})
}
addTodo = (todo) => {
todo.id = Math.random()
// console.log(todo)
let todos = [...this.state.todos, todo]
this.setState({
todos
})
}
button = () => {
// console.log(this.state)
const allTodos = this.state.todos.filter(todo => {
console.log(todo)
})
// const id = 10;
// console.log(allTodos)
// allTodos.forEach(todo => {
// // console.log(todo)
// const arr = new Array(todo)
// arr.pop()
// })
}
render(){
// console.log(this.state)
return (
<div className="App">
<div className="container">
<header className="text-center text-light my-4">
<h1>ToDo - List</h1>
<form>
<input type="text" name="search" placeholder="Search ToDo's" className="form-control m-auto"/>
</form>
</header>
<PrintTodo addTodo={this.state.todos} deleteTodo={this.deleteTodo}/>
<Addtodo addTodo={this.addTodo} allTodos={this.button}/>
</div>
</div>
)
}
}
export default App;
PrintTodo Component
import React from 'react'
const printTodo = ({addTodo, deleteTodo, }) => {
// console.log(addTodo)
const todoList = addTodo.length ? (
addTodo.map(todo => {
return (
<ul className="list-group todos mx-auto text-light" key={todo.id}>
<li className="list-group-item d-flex justify-content-between align-items-center">
<span>{todo.content}</span>
<i className="far fa-trash-alt delete" onClick={()=>{deleteTodo(todo.id)}}></i>
</li>
</ul>
)
})
) : (
<p className="text-center text-light">You don't have any ToDo's</p>
)
return (
<div>
{todoList}
</div>
)
}
export default printTodo
AddTodo Component
import React, { Component } from 'react'
class Addtodo extends Component{
state = {
content: ""
}
handleChange = (e) => {
this.setState({
content: e.target.value
})
}
handleSubmit = (e) => {
e.preventDefault()
this.props.addTodo(this.state)
this.setState({
content: ""
})
}
render(){
// console.log(this.props.allTodos)
return(
<div>
<form className="text-center my-4 add text-light" onSubmit={this.handleSubmit}>
<label htmlFor="add">Add a New ToDo</label>
<input onChange={this.handleChange} type="text" name="add" id="add" className="form-control m-auto" value={this.state.content}/>
</form>
<button onClick={() => {this.props.allTodos()}}>Clear Whole List</button>
</div>
)
}
}
export default Addtodo
In your app.js make this your button component.
button = () => {
this.setState({todos: []})
})
Resetting your todos to an empty array will delete all your todos.

Cannot Update Data in Reactjs+Laravel App

I have an offer-adding feature in my app. my front end is on react js and the backend is on Laravel. I have created a route to update the data and called it using Axios but I don't know what I am doing wrong. Any type of Help will be appreciated Thank You!
this is my route in api.php
Route::put('offers/{id}', 'Api\Offer\OfferController#update');
This is my OfferController
public function update(Request $request, $id)
{
$offer = Offer::findOrFail($id);
$offer->update($request->all());
return $offer;
}
This is my API call function for update
export const updateItem = (offertitle,offerdescription,vid,id) => {
return axios
.put(
`/api/offers/${id}`,
{
offertitle:offertitle,
offerdescription:offerdescription,
vid:vid
},
{
headers: { 'Content-Type': 'application/json' }
}
)
.then(function (response) {
console.log(response)
})
}
OfferComponent
export default class Offer extends React.Component{
constructor() {
super()
this.state = {
offertitle: '',
offerdescription: '',
editDisabled: false,
offers: [],
redirect: false,
vid:'',
offerid:''
}
this.onSubmit = this.onSubmit.bind(this)
this.onChange = this.onChange.bind(this)
}
componentDidMount() {
this.getAll()
if (sessionStorage.getItem('user')) {
vendorprofile().then(res => {
this.setState({
vid: res.user.vid
})
})
}
else {
this.setState({ redirect: true });
}
}
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
getAll = () => {
getList().then(data => {
this.setState(
{
offertitle:'',
offerdescription:'',
offers: [...data]
},
() => {
console.log(this.state.offers)
}
)
})
}
onSubmit = e => {
e.preventDefault()
addItem({offertitle: this.state.offertitle, offerdescription: this.state.offerdescription,vid: this.state.vid}).then(() => {
this.getAll()
})
this.setState({
offertitle: '',
offerdescription:'',
vid:''
})
}
onUpdate = e => {
e.preventDefault()
updateItem({ offertitle: this.state.offertitle, offerdescription: this.state.offerdescription, offerid: this.state.offerid, vid: this.state.vid }).then(() => {
this.getAll()
})
this.setState({
offertitle: '',
offerdescription: '',
vid:'',
editDisabled: ''
})
this.getAll()
}
onEdit = (offerid, e) => {
e.preventDefault()
var data = [...this.state.offers]
data.forEach((offers,index) => {
if (offers.offerid === offerid) {
this.setState({
offerid: offers.offerid,
offertitle: offers.offertitle,
offerdescription: offers.offerdescription,
editDisabled: true
})
}
})
}
onDelete = (val, e) => {
e.preventDefault()
deleteItem(val)
var data = [...this.state.offers]
data.filter(function (offers, index) {
if (offers.offerid === val) {
data.splice(index, 1)
}
return true
})
this.setState({ offers: [...data] })
}
render() {
if (this.state.redirect) {
return (
<Redirect to="/stsignin" />
)
}
return (
<div>
<Pane />
<div className="container" style={{ marginTop : 150}}>
<form>
<div className="form-group">
<div className="row">
<div className="col-md-12">
<label>OFFER TITLE</label>
<input
type="text"
className="form-control"
id="offertitle"
name="offertitle"
value={this.state.offertitle || ''}
onChange={this.onChange.bind(this)}
/>
<label>OFFER DESCRIPTION</label>
<input
type="text"
className="form-control"
id="offerdescription"
name="offerdescription"
value={this.state.offerdescription || ''}
onChange={this.onChange.bind(this)}
/>
</div>
</div>
</div>
{!this.state.editDisabled ? (
<button
type="submit"
onClick={this.onSubmit.bind(this)}
className="btn btn-success btn-block"
>
Submit
</button>
) : (
''
)}
{this.state.editDisabled ? (
<button
type="submit"
onClick={this.onUpdate.bind(this)}
className="btn btn-primary btn-block"
>
Update
</button>
) : (
''
)}
</form>
<table className="table">
<tbody>
<tr>
<th>OFFER_TITLE</th>
<th>OFFER_DESCRIPTION</th>
</tr>
{this.state.offers.map((offers,index) => (
<tr key={index}>
<td className="text-left">{offers.offertitle}</td>
<td className="text-left">{offers.offerdescription}</td>
<td className="text-right">
<button
href=""
className="btn btn-info mr-1"
disabled={this.state.editDisabled}
onClick={this.onEdit.bind(
this,
offers.offerid
)}
>
Edit
</button>
<button
href=""
className="btn btn-danger"
disabled={this.state.editDisabled}
onClick={this.onDelete.bind(
this,
offers.offerid
)}
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}
}```
Error 404 Might mean that the offer specified in the link doesn't exist and thus can't be updated. Check if you have an order with the id that you are searching in the database. However, posting your entire response might show us more information. A simple 404 is pretty vague, you might want to copy paste that in.
That being said, i recommend using Eloquent for these kind of routes. You can basically change your route to /offers/{offer} and then instead of typing $id as a variable for that function and then finding the offer by id you can just simply query $offer->update(your_data) and it would work as expected. It is exactly the same thing but just keeps it cleaner and removes any basic mistakes

Using input textbox in react to show a dropdown of suggestions

I have a list of topics and groups being returned from an API call. Topics belongs to at least 1 or more groups. The topics are currently filtered by the groups that are selected. Each group selected is set or removed in the selectedGroups state. I have an input search box which is used to help the user find a topic, when they start typing in the textbox I want a dropdown just below showing if any topic titles match their search input. When they click that topic it should only show that topic in the topics state.
Example.. if I type..
"Jo"
We get a dropdown of topics just below as suggestions and should render as in the dropdown:-
John..
Johnny..
Joan..
etc
Then when we click one of these topics in the dropdown, the state for topics update. So yes it will just show one topic in this case.
I have the search input and onchange method called handleInputChange
I am getting an error: Property 'search' does not exist on type 'PracticeAreas'. and not sure where I should be heading towards getting this to work correctly. Any help would be really grateful, thanks
I have included example data from the API call
And the react script
Main:
import * as React from 'react';
import './PracticeAreas.css';
import IReportGroup from 'src/model/IReportGroup';
import { Loader } from '../loader/Loader';
import Suggestions from './Suggestions'
export interface IGroupTopics {
id: string
name: string,
groups: string[]
}
interface IOwnProps {
}
interface IOwnState {
groups: IReportGroup[],
topics: IGroupTopics[],
selectedGroups: IReportGroup[],
query: string,
}
class PracticeAreas extends React.Component<IOwnProps, IOwnState> {
constructor(props: IOwnProps) {
super(props);
this.state = {
groups: [],
topics: [],
selectedGroups: [],
query: ""
}
}
public render() {
const { topics } = this.state;
return topics.length > 0 ?
this.renderData(topics) :
<Loader />
}
public renderData(data: any) {
return (
<div className="col-md-12 practiceAreas">
<h1>Practice Areas</h1>
<div className="selection-refinement">
<div className="refinement-search">
<form>
<input
placeholder="Search for..."
ref={input => this.search = input}
onChange={this.handleInputChange}
/>
<Suggestions topics={this.state.topics} />
</form>
</div>
</div>
<ul className="list-inline groupedTags">
{this.state.groups.map((item,i) =>
<li key={i}>
<a className={"navigator-tags " + (this.groupInState(item) ? "active" : "")} onClick={() => this.setSelectedGroups(item)}>
{item.name}
</a>
</li>
)}
</ul>
<div className="row practiceAreasContainer">
{this.state.topics.filter(topic => this.topicInGroupSelection(topic)).map((item,i) =>
<div key={i} className="result">
<div className="col-md-6 result-item">
<div className="item-container default shadowed item-content highlight row">
<div className="col-sm-12 no-padding">
<p>Editor: John Sinclair, Eric Draven, Coco Zames</p>
<p>Beiten Burkhardt</p>
<div className="row no-margin">
<div className="col-12 col-sm-10 text-content">
<h3>
<a href="#" >{item.name}</a>
</h3>
<p className="summary">
Summary
</p>
</div>
<div className="col-10 col-sm-2 links-container rhs">
Compare
<div className="divider" />
View
</div>
</div>
</div>
</div>
</div>
</div>
)}
</div>
<div className="row text-center">
<a className="lex-primary-btn medium-btn">Load more</a>
</div>
</div>
);
}
public handleInputChange = () => {
this.setState({
query: this.search.value
}, () => {
if (this.state.query && this.state.query.length > 1) {
// this.showDropdown()
if (this.state.query.length % 2 === 0) {
this.state.topics
}
} else if (!this.state.query) {
// this.hideDropdown()
}
})
}
public componentDidMount() {
fetch(`.../api/v2/navigator/reports/topics`, {
method: "GET",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}})
.then((res) => res.json()
.then((data) => {
this.setState({
groups: data.groups,
topics: data.data
});
}));
}
public setSelectedGroups = (group: IReportGroup) => {
// remove from state
if (this.groupInState(group)) {
this.setState(state => ({
selectedGroups: state.selectedGroups.filter(t => t.id !== group.id)
}));
// set state
} else {
this.setState(previousState => ({
selectedGroups: [...previousState.selectedGroups, group]
}));
}
}
public topicInGroupSelection = (topic: IGroupTopics) => {
return (this.state.selectedGroups.length > 0 ? this.state.selectedGroups.some(item => topic.groups.some(group => group === item.id)) : true)
}
public groupInState = (group: IReportGroup) => {
return this.state.selectedGroups.some(item => group.id === item.id);
}
}
export default PracticeAreas
Suggestions (which should topics in the state):
import * as React from 'react';
const Suggestions = (props) => {
const options = props.topics.map(r => (
<li key={r.id}>
{r.name}
</li>
))
return <ul>{options}</ul>
}
export default Suggestions
Data ex:
<ReportSelectionCriteriaResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/">
<Data xmlns:d2p1="http://schemas.datacontract.org/2004/07/">
<d2p1:NavigatorReportSelection>
<d2p1:About>test title 4</d2p1:About>
<d2p1:Groups xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:guid>d21384b5-27be-4bfc-963d-0d2ad40dbbfb</d4p1:guid>
</d2p1:Groups>
<d2p1:Id>2fb2783c-f48e-4d49-8098-0d39e4a16e7a</d2p1:Id>
<d2p1:Name>Test</d2p1:Name>
<d2p1:ParentId i:nil="true"/>
<d2p1:Selected>false</d2p1:Selected>
<d2p1:Type>Topics</d2p1:Type>
<d2p1:Visible>true</d2p1:Visible>
</d2p1:NavigatorReportSelection>
<d2p1:NavigatorReportSelection>
<d2p1:About i:nil="true"/>
<d2p1:Groups xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:guid>2fb2783c-f48e-4d49-8098-0d39e4a16e7a</d4p1:guid>
</d2p1:Groups>
<d2p1:Id>47cb7f1d-2267-426c-9f7f-0df3b9291fb7</d2p1:Id>
<d2p1:Name>Another test topic</d2p1:Name>
<d2p1:ParentId i:nil="true"/>
<d2p1:Selected>false</d2p1:Selected>
<d2p1:Type>Topics</d2p1:Type>
<d2p1:Visible>true</d2p1:Visible>
</d2p1:NavigatorReportSelection>
</Data>
<Groups xmlns:d2p1="http://schemas.datacontract.org/2004/07/">
<d2p1:NavigatorReportSelectionGroup>
<d2p1:Focused>false</d2p1:Focused>
<d2p1:Id>2fb2783c-f48e-4d49-8098-0d39e4a16e7a</d2p1:Id>
<d2p1:Name>Allan's Test group</d2p1:Name>
<d2p1:Order>0</d2p1:Order>
<d2p1:Type>Topics</d2p1:Type>
</d2p1:NavigatorReportSelectionGroup>
<d2p1:NavigatorReportSelectionGroup>
<d2p1:Focused>false</d2p1:Focused>
<d2p1:Id>47cb7f1d-2267-426c-9f7f-0df3b9291fb7</d2p1:Id>
<d2p1:Name>Another test topic group</d2p1:Name>
<d2p1:Order>1</d2p1:Order>
<d2p1:Type>Topics</d2p1:Type>
</d2p1:NavigatorReportSelectionGroup>
</Groups>
</ReportSelectionCriteriaResponse>

React: change order list when button clicked

I am making my first app with Javascript and React and started with a page which views a shopping list. It gets the items from an api call.
If the user clicks on the button 'done' (or should I use an checkbox?) This product should go to the bottom of the list (and be grayed out with css but thats not the problem).
The problem is, I have no clue how to do this. Can anyone help me out a bit?
This is my code:
import React from 'react';
//import image from '../images/header.png';
//import Collapsible from './Collapsible';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
orders: []
}
}
componentWillMount() {
localStorage.getItem('orders') && this.setState({
orders: JSON.parse(localStorage.getItem('orders')),
isLoading: false
})
}
componentDidMount() {
if (!localStorage.getItem('orders')){
this.fetchData();
} else {
console.log('Using data from localstorage');
}
}
fetchData() {
fetch('http://localhost:54408/api/orders/all/15-03-2018')
.then(response => response.json())
.then(parsedJSON => parsedJSON.map(product => (
{
productname: `${product.ProductName}`,
image: `${product.Image}`,
quantity: `${product.Quantity}`,
isconfirmed: `${product.IsConfirmed}`,
orderid: `${product.OrderId}`
}
)))
.then(orders => this.setState({
orders,
isLoading: false
}))
.catch(error => console.log('parsing failed', error))
}
componentWillUpdate(nextProps, nextState) {
localStorage.setItem('orders', JSON.stringify(nextState.orders));
localStorage.setItem('ordersDate', Date.now());
}
render() {
const {isLoading, orders} = this.state;
return (
<div>
<header>
<img src="/images/header.jpg"/>
<h1>Boodschappenlijstje <button className="btn btn-sm btn-danger">Reload</button></h1>
</header>
<div className={`content ${isLoading ? 'is-loading' : ''}`}>
<div className="panel">
{
!isLoading && orders.length > 0 ? orders.map(order => {
const {productname, image, quantity, orderid} = order;
return<div className="product" key={orderid}>
<div className="plaatjediv">
<img className="plaatje" src={image} />
</div>
<div className="productInfo">
<p>{productname}</p>
<p>Aantal: {quantity}</p>
<p>ID: {orderid}</p>
</div>
<div className="bdone">
<button className="btn btn-sm btn-default btndone">Done</button>
</div>
</div>
}) : null
}
</div>
<div className="loader">
<div className="icon"></div>
</div>
</div>
</div>
);
}
}
export default App;
You can achieve by using this :
this.handleDoneAction = event = > {
let itemIndex = event.target.getAttribute("data-itemIndex");
let prevOrders = [...this.state.orders];
var itemToMoveAtLast = prevOrders.splice(itemIndex, 1);
var updatedOrderList = prevOrders.concat(itemToMoveAtLast);
this.setState({order: updatedOrderList})
}
I have attach an event handler on the button handleDoneAction.
<button className="btn btn-sm btn-default btndone" data-itemIndex={index} onClick={this.handleDoneAction}>Done</button>
the attribute data-itemIndex is the index of the object in orders array.
And your map function will be like this:
orders.map((order, index) => {
//content
})
ANd for the different style effects on the done products, I will suggest you to use different array for all done products.

Resources