I'm new to React and made an app that allows searches to be saved. This will pull JSON but is currently pulling from a static array data
. I'm having trouble being able to delete searches from the search list.
Here's the jsbin: http://jsbin.com/nobiqi/edit?js,output
Here's my delete button element:
var DeleteSearch = React.createClass({
render: function() {
return (
<button onClick="this.props.deleteSearchItem" value={index}><i className="fa fa-times"></i>
</button>
);
}
});
and my function
deleteSearchItem: function(e) {
var searchItemIndex = parseInt(e.target.value, 10);
console.log('remove task: %d', searchItemIndex);
this.setState(state => {
state.data.splice(searchItemIndex, 1);
return { data: state.data };
});
}
I've tried following tutorials and I'm not sure where to go from here. How can I delete the search items?
To remove an object from a state array in React: Use the filter() method to iterate over the array. On each iteration, check if a condition is met. Set the state to the new array that the filter method returned.
To delete a record(s) the name is sent from the client-side to the server-side. Observe the DELETE component. import axios from "axios"; import { useState } from "react"; const DELETE = (props) => { const [message, setMessage] = useState(False); return ( <div> {! message ? ( props.
Let me guess, Are you looking for something like this?
class Example extends React.Component {
constructor(){
this.state = {
data: [
{id:1, name: 'Hello'},
{id:2, name: 'World'},
{id:3, name: 'How'},
{id:4, name: 'Are'},
{id:5, name: 'You'},
{id:6, name: '?'}
]
}
}
// shorter & readable
delete(item){
const data = this.state.data.filter(i => i.id !== item.id)
this.setState({data})
}
// or this way, it works as well
//delete(item){
// const newState = this.state.data.slice();
// if (newState.indexOf(item) > -1) {
// newState.splice(newState.indexOf(item), 1);
// this.setState({data: newState})
// }
//}
render(){
const listItem = this.state.data.map((item)=>{
return <div key={item.id}>
<span>{item.name}</span> <button onClick={this.delete.bind(this, item)}>Delete</button>
</div>
})
return <div>
{listItem}
</div>
}
}
React.render(<Example />, document.getElementById('container'));
In this example pay attention how i'm binding delete
method and pass there new parameter. fiddle
I hope it will help you.
Thanks
OP here. Since I know more about React four years later and this still gets views I figured I'd update this with how I'd go about it now.
SavedSearches.js
import React from 'react'
import { SearchList } from './SearchList'
let data = [
{index: 0, name: "a string", url: 'test.com/?search=string'},
{index: 1, name: "a name", url: 'test.com/?search=name'},
{index: 2, name: "return all", url: 'test.com/?search=all'}
];
let startingIndex = data.length;
export class SavedSearches extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
url: '',
index: startingIndex,
data: data
}
this.deleteSearch=this.deleteSearch.bind(this)
}
deleteSearch(deleteThis) {
console.log(deleteThis);
let newData = this.state.data.filter( searchItem => searchItem.index !== deleteThis.index )
this.setState({
data: newData
})
}
render() {
return (
<div className="search-container">
<SearchList data={this.state.data} onDelete={this.deleteSearch}/>
</div>
)
}
}
Here I created a method called deleteSearch
that takes an object as a parameter. It then runs .filter
on the this.state.data
array to create a new array that includes all items that don't meet the condition. The condition checks if the id of each object in the data array matches the id of the parameter. If so, then it is the one that is being deleted. The new array that is created by .filter
is set to a variable called newData
, and then I update the state with the newData
array.
I then pass this method to the SearchList
component in a prop called onDelete
.
This method is also bound in the constructor using .bind()
so that this
will refer to the correct this
when the method is passed down the component tree.
SearchList.js
import React from 'react'
import { SearchItem } from './SearchItem'
export class SearchList extends React.Component {
render() {
let searchItems = this.props.data.map((item, i) => {
return (
<SearchItem index={i} searchItem={item} url={item.url} onDelete={this.props.onDelete}>
{item.name}
</SearchItem>
);
});
return (
<ul>
{searchItems}
</ul>
);
}
}
My deleteSearch
method is just passing through the component tree here. SearchList
receives the method as a props this.props.onDelete
and passes it to SearchItem
.
The other major key here is that the parameter in the map function is being passed as props: searchItem={item}
. This will allow the entire current object to be accessed via props; and if you remember, my deleteSearch
function takes an object as a parameter.
SearchItem.js
import React from 'react'
export class SearchItem extends React.Component {
constructor(props) {
super(props);
this.handleDelete=this.handleDelete.bind(this)
}
handleDelete() {
this.props.onDelete(this.props.searchItem)
}
render() {
return (
<li key={this.props.index}> {/* Still getting a console error over this key */}
<a href={this.props.url} title={this.props.name}>
{this.props.children}
</a>
({this.props.url})
<button onClick={this.handleDelete} value={this.props.index}><i className="fa fa-times"></i>
</button>
</li>
);
}
};
Now my method arrives where it will be used. I create a handler method handleDelete
and inside I access the deleteSearch
method with this.props.onDelete
. I then pass it the object of the list item that is being clicked on with this.props.searchItem
.
In order for this to work when a user clicks, I had to add an onClick
event listener that calls my handler method, like this: onClick={this.handleDelete}
. The final step is to bind this.handleDelete
in the SearchItem
constructor method.
Now, clicking on the button will remove the item from the this.state.data
array. For an example of how to add an item to the array, see my repository
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With