#javascript #reactjs #ecmascript-6 #react-redux
#javascript #reactjs #ecmascript-6 #реагировать-redux
Вопрос:
Я пишу программу react, в которой данные будут извлекаться через API и отображаться в таблице. Есть 3 основных файла App.js , Table.js и Search.js и Button.js . Данные отображаются, поиск работает, но кнопка удаления не работает. Я написал функцию для кнопки удаления, и я предполагаю, что в этом что-то не так, но не знаю, что.
App.js
import React, { Component } from 'react';
import './App.css';
import Table from './components/Table';
import Search from './components/Search';
//API config
const DEFAULT_QUERY = 'react';
const PATH_BASE = 'https://hn.algolia.com/api/v1';
const PATH_SEARCH = '/search';
const PARAM_SEARCH = 'query=';
const url = `${PATH_BASE}${PATH_SEARCH}?${PARAM_SEARCH}${DEFAULT_QUERY}`;
class App extends Component {
constructor(){
super();
//here searchText is set to DEFAULT_QUERY which will return the result for keyword "redux"
//refer line 8 to change
this.state={
searchText:'',
result:''
}
this.onDismiss=this.onDismiss.bind(this);
this.onSearchChange=this.onSearchChange.bind(this);
this.searchStories=this.searchStories.bind(this);
//this.isSearched=this.isSearched.bind(this);
}
//to add a delete button
onDismiss=(id)=>{
//filter out item array and return results with no matched id
const deleteList=this.state.list.filter(item=>item.objectID!==id);
//setting state of list to lastest deleteList
this.setState({
result:deleteList
})
}
//to add a search bar
onSearchChange=(e)=>{
//set state to value in search bar
this.setState({
[e.target.name]:e.target.value
})
}
searchStories=(result)=>{
this.setState({
result
});
}
//after mounting will fetch the api data
componentDidMount(){
fetch(url)
.then(response => response.json())
.then(result => this.searchStories(result));
}
render() {
const {result,searchText}=this.state;
if(!result){
return null;
}
return(
<div className="page">
<div className="interactions">
<Search
searchText={searchText}
onSearchChange={this.onSearchChange}
>
Search
</Search>
</div>
<Table
list={result.hits}
onDismiss={this.onDismiss}
searchText={searchText}/>
</div>
)
}
}
export default App;
Table.js
import React from 'react';
import Button from './Button';
const Table=(props)=>{
const {list,searchText,onDismiss}=props;
return(
<div className="table">
{/*Filter out item title and search title and give away results from item array */}
{list.filter((item)=>{
{/*The includes() method determines whether an array includes a certain value among its entries
, returning true or false as appropriate. */}
return item.title.toLowerCase().includes(searchText.toLowerCase());}).map((item)=>{
return(
<div key={item.objectID} className="table-row">
<span style={{ width: '40%' }}>
<a href={item.url}>{item.title}</a>
</span>
<span style={{ width: '30%' }}>
{item.author}
</span>
<span style={{ width: '10%' }}>
{item.num_comments} comments
</span>
<span style={{ width: '10%' }}>
${item.points} points
</span>
<span style={{ width: '10%' }}>
<Button className="button-inline" onClick={()=>onDismiss(item.objectID)}>delete</Button>
</span>
</div>
)})}
</div>
)
}
export default Table;
Button.js
import React from 'react';
const Button=(props)=>{
const{onclick,className='',children}=props;
return(
<div>
<button onClick={onclick} className={className} >{children}</button>
</div>
)
}
export default Button;
Комментарии:
1. попробуйте изменить onDismiss={this.onDismiss} на onDismiss={() => this.onDismiss}
Ответ №1:
Ваша кнопка нуждается в небольшом изменении:
<button onClick={onClick} className={className} >{children}</button>
Обработчику необходимо ссылаться на переданные реквизиты, в которых есть this.props.onClick, а не this.props.onclick (который у вас был).
Ошибка, с которой вы столкнулись, может быть исправлена путем изменения App.js:
onDismiss = id => {
if (id) {
const deleteList = this.state.list.filter(item => item.objectID !== id);
// setting state of list to lastest deleteList
this.setState({
result:deleteList
})
}
}
Ответ №2:
В изменении компонента кнопки
const{onclick,className='',children}=props;
Для
const{onClick,className='',children}=props;
Также кажется, что вы не установили list в состояние, поэтому при попытке получить доступ к this.state.list.filter он выдаст ошибку.
onDismiss=(id)=>{
const deleteList=this.state.result.hits.filter(item=>item.objectID!==id);
this.setState({
result:{...this.state.result,hits:deleteList}
})
}
Комментарии:
1. Это
onClick
вместоonclick
, вы допустили опечатку2. @Treycos это не работает. Это приводит к сбою приложения, выдавая ошибку: TypeError: не удается прочитать свойство ‘filter’ из undefined
3. @user11066242 В коде ` const deleteList=this.state.list.filter(item=>item.ObjectId!==id); ` функции onDismiss вы пытаетесь получить доступ к this.state.list. Откуда берется список? Вы где-то переводите список в состояние
4. @Muljayan понял, попал в точку. Это был старый код, и я не обновлял его в соответствии со значением состояния. Вместо этого я заменил его на result.hits. фильтруйте, и это сработало. Спасибо
5. @user11066242 похоже, что ваша правка по какой-то причине была отменена моей правкой. Попробуйте отредактировать его еще раз.