Remove item from array react js - reactjs

I'm having trouble with removing an object from an array. I have tried many options and nothing works.
Please help me solve this problem.
Thanks for your help
My array:
export const SavedList = [
{
word: 'hello',
translate: 'привет',
note: 'say say'
}
]
Remove callback (deletePost)
class Menu extends Component {
state = {
word: '',
translate: '',
note: '',
data: SavedList,
}
deletePost =(id)=>{
this.setState({
data : this.state.data.filter((el)=> el.id !== id)
})
}
render() {
return (
<div className="content">
<Routes>
<Route path="/" element={<Layout />}>
<Route path="saved" element={<Saved data={this.state.data} del={this.deletePost}/>}/>
</Route>
</Routes>
<div>
</div>
</div>
);
}
}
export default Menu;
here button delete with onClick
class Saved extends Component {
render() {
const sl = this.props.data.map((sl, id) => {
return (
<div className="saved-card" key={id}>
<div className="content">
<p>{id}</p>
<p>{sl.word}</p>
<p>{sl.translate}</p>
<p>{sl.note}</p>
</div>
<div className="btn-block">
<button
onClick={() => this.props.del(id)}
type="button"
className="delete-btn"
>
delete
</button>
</div>
</div>
);
});
return (
<div>
<h2>Saved list</h2>
<div className="saved-inner">
<div className="saved-list">{sl}</div>
</div>
</div>
);
}
}
export default Saved;

This issue is because el.id doesn't have any value in delete Post Function. That function also needs to have an ID variable, I have named it as i_di.
class App extends Component {
state = {
word: '',
translate: '',
note: '',
data: SavedList,
}
deletePost =(id)=>{
this.setState({
data : this.state.data.filter((el, i_di)=> i_di !== id )
})
}
render() {
return (
<div className="content">
{<Saved data={this.state.data} del={this.deletePost}/>}
</div>
);
}
}
export default App;

Related

How can I insert row div for every 3rd entry in props?

I've got a set of dashboards that display in bootstrap cards on a front page and I would like to wrap them in a div with the class row for every 3rd entry. I was thinking about marking my dashboard component with the DB id from props and use a modulus function, but that will cause problems if an ID is deleted
Dashboard component:
export type DashboardProps = {
id: number
title: string
description: string
}
const Dashboard: React.FC<{ dashboard: DashboardProps }> = ({ dashboard }) => {
return (
<>
<div className="col-sm-12 col-lg-4">
<div className="card bg-light h-100">
<div className="card-header">
{dashboard.title}
</div>
<div className="card-body d-flex flex-column">
<p className="card-text">
{dashboard.description}
</p>
<a className="btn btn-info text-center mt-auto"
onClick={() =>
Router.push("/dashboard/[id]", `/dashboard/${dashboard.id}`)
}
>Go to dashboard</a>
</div>
</div>
</div>
</>
)
}
export default Dashboard
Index page:
type Props = {
dashboards: DashboardProps[]
}
export const getServerSideProps: GetServerSideProps = async () => {
const dashboards = await prisma.dashboard.findMany({
orderBy: { id: "asc", },
})
return {
props: JSON.parse(JSON.stringify({ dashboards })),
}
}
const Index: React.FC<Props> = (props) => {
const { data: session, status } = useSession()
if (status === "loading") {
return (
<Spinner />
)
}
if (!session) {
return (
<Layout>
<AccessDenied />
</Layout>
)
}
return (
<Layout>
<h1>Dashboards</h1>
{props.dashboards.map((dashboard) => (
<Dashboard dashboard={dashboard} />
))}
</Layout>
)
}
export default Index
I could also potentially wrap them in a single div with class row, but I would need to enforce a top/bottom margin so the cards don't stack right on top of each other. Any tips to get me rolling on this would be greatly appreciated!
.map provides index, you this to find every 3rd element.
//...
{
props.dashboards.map((dashboard, index) =>
(index + 1) % 3 === 0 ? (
<div>
<Dashboard key={dashboard.id} dashboard={dashboard} />
</div>
) : (
<Dashboard key={dashboard.id} dashboard={dashboard} />
)
)
}

Some Problem in Params, Not getting the Emp id ? possible solution

Error Are : Uncaught TypeError: Cannot read properties of undefined (reading 'params'),
The above error occurred in the component:
I might think i problem is in the passing props
App component
class App extends Component {
render() {
return (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Navigate to={"/card"} />}></Route>
<Route path="/card" element={<Card />} />
<Route path="/edit/:id" element={<EditEmployee />} />
</Routes>
</BrowserRouter>
);
}
}
card Component
const emp1 = {
empId: 100,
empName: "Jack",
age: 30,
salary: 50000,
image: image1,
achievements:
"Has got 3 bravo awards and 1 MVP award. Has worked on cutting edge technologies as well",
};
const emp2 = {
empId: 101,
empName: "Jane",
age: 24,
salary: 40000,
image: image2,
achievements: "No major achievements so far",
};
export default class Card extends React.Component {
empArr = [emp1, emp2];
render() {
return (
<div>
<h3 className="text-center text-primary">Employee Details</h3>
<div className="row">
{this.empArr.map((emp) => (
<Employee key={emp.empId} emp={emp} />
))}
</div>
</div>
);
}
}
Employee Component
class Employee extends React.Component {
state = {
achievements: null,
edit: null,
};
handleEdit = () => {
this.setState(() => ({ edit: true }));
};
handleView = () => {
this.setState(() => ({ achievements: this.props.emp.achievements }));
};
render() {
const { emp } = this.props;
if (this.state.edit) {
return <Navigate to={"/edit/" + emp.empId} push></Navigate>;
}
return (
<div className="card" style={{ width: 200 }}>
<img
className="card-img-top"
src={emp.image}
height="200"
alt="Card cap"
/>
<div className="card-body">
<h5 className="card-title text-center">{emp.empName}</h5>
<p className="card-text">
<span>Id: {emp.empId}</span>
<br />
<span>Age: {emp.age}</span>{" "}
{emp.age < 25 && <span className="text-info"> - Fresher</span>}
<br />
<span>Salary: {emp.salary}</span>
<br />
</p>
<p>
<i>{this.state.achievements}</i>
</p>
<button
type="button"
className="btn btn-primary"
onClick={this.handleEdit}
>
Edit
</button>
<button className="btn btn-success" onClick={this.handleView}>
View
</button>
</div>
</div>
);
}
}
EditEmployee Component
class EditEmployee extends React.Component {
render() {
return <h3>The selected ID is {this.props.match.params.id}</h3>;
}
}
export default EditEmployee;
Result should be like this
WHAT I WANT
but i am getting this error on click edit
enter image description here
WHAT I AM GETTING /ERROR IMAGE
You want to get the params via the useParams() hook:
const EditEmployee = () => {
const id = useParams()
return (
<h3>The selected ID is {id}</h3>;
)
}
export default EditEmployee;
Sorry that's a functional component. You can translate it to a class...
Did you just console.log(this.props) in your EditEmployee to see what you're getting?
You may need to wrap your class component in a function component as illustrated here.
Documentation here

TypeError: author is undefined

creating react AuthorQuiz app
I have tow main file
1- AuthorQuiz.js
2- index.js
I have a problem with Turn component
AuthorQuiz.js
enter code here
function Turn({ author, books }) {
return (
<div className="row turn" style={{ backgroundColor: 'white' }}>
<div className="col-4 offset-1">
<img src={author.imageUrl} className="authorImage" alt="Author" />
</div>
<div className="col-6">
{books.map((title) => <p>{title}</p>)}
</div>
</div>);
}
function AuthorQuiz(turnData) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...turnData}/>
<Continue/>
<Footer/>
</div>
);
}
index.js
enter code here
const authors = [
{
name: 'mark Twin',
imageUrl: 'images/authors/mark.jpg',
imageSource: 'google wiki',
books: ['The Advance of Finn']
}
];
const state={
turnData:{
author:authors[0],
books:authors[0].books
}
}
ReactDOM.render(<AuthorQuiz {...state}/>,
document.getElementById('root'));
but when I run my code I get an error
TypeError: author is undefined
Turn
C:/Users/HP/Desktop/React pro/authorquiz/src/AuthorQuiz.js:18
You should use {state.turnData} instead of {...state}.
Because the result of {...state} is like this: {turnData: {…}}
So { author, books } can't work correctly.
const state={
turnData:{
author:authors[0],
books:authors[0].books
}
}
<AuthorQuiz {...state}/>
Spreading the state over the AuthorQuiz is equivalent to:
<AuthorQuiz turnData={state.turnData}/>
But in the AuthorQuiz component:
function AuthorQuiz(turnData) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...turnData}/>
<Continue/>
<Footer/>
</div>
);
}
function AuthorQuiz(turnData) {
...
<Turn {...turnData}/>
...
is equivalent to
function AuthorQuiz(props) {
...
<Turn turnData={
props.turnData
}}/>
...
So you need to add brackets to spread turnData instead of props:
function AuthorQuiz({ turnData }) {
...
<Turn { ...turnData}}/>
...
The AuthorQuiz component is getting the turnData variable as a prop. You should use the spread operator on the props.turnData variable instead.
function AuthorQuiz(props) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...props.turnData}/>
<Continue/>
<Footer/>
</div>
);
}
The props in the AuthorQuiz component look like this:
{
turnData: {
author: { .. },
books: [ .. ]
}
}
Your Turn component wants the author and books props, so you could do this in your AuthorQuiz component.
function AuthorQuiz(props) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...props.turnData} />
{/* or */}
<Turn author={props.turnData.author} books={props.turnData.books} />
<Continue/>
<Footer/>
</div>
);
}
You could also destructure the turnData prop in your component function directly. This makes it clear which props are being drilled down the Turn component without switching to multiple files.
function AuthorQuiz({ turnData: { author, books } }) {
return (
<div className="container-fluid">
<Hero/>
<Turn author={author} books={books} />
<Continue/>
<Footer/>
</div>
);
}

How to pass props through router

I have a list of task, on my dashboard, I want as soon as clicked on a task to get his details.
At the moment I can only retrieve the id of this task, but can't get other information.
When I console.log listTask on my parent component, I get an Array objects that contains all the task:
[ 0: Object { state: "Started", date: "2019-02-11T19:57:26.176Z", _id: "5c6074afd2f8eb5019fd5f54", … }
1: Object { state: "Started", date: "2019-02-11T19:57:26.176Z", _id:"5c60798bacf119510c19f5b1", … }
2: Object { state: "Started", date: "2019-02-11T19:57:26.176Z", _id: "5c607be3c11c2b529615ac26", … }
3: Object { state: "Started", _id: "5c607cfec27d6254c6fe0ca1", projectName: "I LOVE THIS GAME", … } ]
parentComponent.js
async componentDidMount() {
this._isMounted = true
let response = await fetch(`http://localhost:5001/userproject/${taskId}`)
let data = await response.json()
console.log(data) // will show me the array
const projects = data.map(pro => {
return {
id: pro._id,
state: pro.state,
projectName: pro.projectName,
consultants: pro.consultants,
ScrumMasterUsername: pro.scrumMaster.username,
ScrumMasterId: pro.scrumMaster._id,
}
})
return this.setState({
projects: { projects },
})
}
render() {
const { projects } = this.state
const list = (projects && projects.projects) || []
if (!projects) {
return null
}
return (
<div className="dashboard container">
<div className="row">
<div className="col s16 m7 darken-2">
<ProjectList
name={this.state.projects.projectName}
projects={list}
/>
</div>
<div className="col s12 m3 offset-m1">
<Notifications />
</div>
</div>
</div>
)
}
My problem: When tried to get the task details, it retrieves the id of this task and not the other detail:
import React from 'react'
const ProjectDetails = props => {
const id = props.match.params.id
console.log(props) // i can only get the id
return (
<div className="container section project-details">
<div className="card z-depth-0">
<div className="card-content">
<span className="card-title">Project Title - {id} </span>
</div>
</div>
</div>
)
}
export default ProjectDetails
This is how you should do it.
class App extends React.Component {
render() {
return (
<Router>
<div>
<Switch>
<Route path="/" component={Home} />
**<Route path="/about" render={(props) => <About {...props} isAuth={"Authenticated"} />} />**
<Route path="/topics" component={Topics} />
</Switch>
</div>
</Router>
);
}
}
The second route marked between stars, is the one where I am rendering the component and passing a prop isAuth={"Authenticated"}
The above prop will be available inside About component as
const About = (props) => {
return (
<div>
<h1>About={props.isAuth}</h1>
</div>
);
}
Hope this helps you!!

React app state not updating

I am creating a basic React app to hold books on certain shelves and am trying to create the functionality to move books between shelves.
The problem I have is that when I select the new target shelf from the book objects dropdown, the onUpdateShelf method in ListBooks.js does not seem to initiate the update and subsequent state change.
I am new to React, my understanding is that calling the setState function in updateShelf should trigger the re-render with the updated object.
My question then is, is my implementation wrong and where?
App.js
import React, { Component } from 'react'
import ListBooks from './ListBooks'
import * as BooksAPI from './utils/BooksAPI'
import { Route } from 'react-router-dom'
class BooksApp extends Component {
state = {
books: []
}
componentDidMount() {
BooksAPI.getAll()
.then((books) => {
this.setState(() => ({
books
}))
})
}
updateShelf = (book, shelf) => {
console.log(book)
console.log(shelf)
this.books.forEach(b => {
if(b.id === book.id && b.shelf !== book.shelf ) {
b.shelf = shelf
this.setState((currentState) => ({
books: currentState.books
}))
}
});
BooksAPI.update(book, shelf)
}
render() {
return (
<div>
<Route exact path='/' render={() => (
<ListBooks
books={this.state.books}
onUpdateShelf={this.updateShelf}
/>
)} />
</div>
)
}
}
export default BooksApp
And my ListBooks.js
import React, { Component } from 'react';
import PropTypes from 'prop-types'
import './App.css'
const shelves = [
{
key: 'currentlyReading',
name: 'Currently Reading'
},
{
key: 'wantToRead',
name: 'Want To Read'
},
{
key: 'read',
name: 'Read'
}
];
class ListBooks extends Component {
static propTypes = {
books: PropTypes.array.isRequired
}
state = {
showSearchPage: false,
query: ''
}
render() {
const { books, onUpdateShelf } = this.props
function getBooksForShelf(shelfKey) {
return books.filter(book => book.shelf === shelfKey);
}
console.log(books);
return(
<div className="app">
{this.state.showSearchPage ? (
<div className="search-books">
<div className="search-books-bar">
<a className="close-search" onClick={() => this.setState({ showSearchPage: false })}>Close</a>
<div className="search-books-input-wrapper">
{/*
NOTES: The search from BooksAPI is limited to a particular set of search terms.
You can find these search terms here:
https://github.com/udacity/reactnd-project-myreads-starter/blob/master/SEARCH_TERMS.md
However, remember that the BooksAPI.search method DOES search by title or author. So, don't worry if
you don't find a specific author or title. Every search is limited by search terms.
*/}
<input type="text" placeholder="Search by title or author"/>
</div>
</div>
<div className="search-books-results">
<ol className="books-grid"></ol>
</div>
</div>
) : (
<div className="list-books">
<div className="list-books-title">
<h1>My Reads</h1>
</div>
<div className="list-books-content">
<div>
{ shelves.map((shelf) => (
<div key={shelf.key} className="bookshelf">
<h2 className="bookshelf-title">{shelf.name}</h2>
<div className="bookshelf-books">
<ol className="books-grid">
<li>
{ getBooksForShelf(shelf.key).map((book) => (
<div key={book.id} className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${book.imageLinks.thumbnail})` }}></div>
<div className="book-shelf-changer">
<select>
<option value="none" disabled>Move to...</option>
<option value="currentlyReading" onClick={() => onUpdateShelf(book, 'currentlyReading')} >Currently Reading</option>
<option value="wantToRead" onClick={() => onUpdateShelf(book, 'wantToRead')} >Want to Read</option>
<option value="read" onClick={() => onUpdateShelf(book, 'read')} >Read</option>
<option value="none" onClick={() => onUpdateShelf(book, '')} >None</option>
</select>
</div>
</div>
<div className="book-title">{book.title}</div>
<div className="book-authors">{book.author}</div>
</div>
))}
</li>
</ol>
</div>
</div>
)) }
</div>
</div>
<div className="open-search">
<a onClick={() => this.setState({ showSearchPage: true })}>Add a book</a>
</div>
</div>
)}
</div>
)
}
}
export default ListBooks
When you passe updateShelf to your component ListBooks, you lose the value of this inside updateShelf, and as a result this.books will be undefined.
You can solve this by, either doing this inside the constructor of BooksApp :
this.updateShelf = this.updateShelf.bind(this)
Or by using arrow functions:
<Route exact path='/' render={() => (
<ListBooks
books={this.state.books}
onUpdateShelf={() => { this.updateShelf()} }
/>
)} />
EDIT
You are already using arrow functions inside BooksApp, so what I said before isn't necessary.
But still, you should use this.state.books and not this.books inside updateShelf.

Resources