我想这是React的基础,但是我不确定如何使它正常工作,基本上,当我删除,创建或编辑组件中的任何内容时,我希望更改实时进行而无需刷新页面,我已经通过搜索功能在某种程度上实现了这一目标,但不能完全确定如何使用删除功能,例如:
这是我正在使用的工具,如何将其与axios删除功能一起使用? 谢谢
import { connect } from 'react-redux';
import { fetchTournaments } from '../actions/tournaments';
import Item from './Item';
import EditTournament from './EditTournament';
import axios from 'axios';
import '../styles/Item.css';
class SearchAndDisplay extends React.PureComponent {
componentDidMount() {
this.props.fetchTournaments();
}
state = {
searchCriteria: '',
isLoading: false
};
handleChange = event => {
this.setState({
searchCriteria: event.target.value
});
};
async handleDelete(id) {
const url = `http://localhost:4000/tournaments/`;
await axios
.delete(url + id)
.then(res => {
console.log(res.data);
})
.catch(err => {
console.log(err);
});
}
formatDate(date) {
let options = {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: false
};
let newDate = new Date(Date.parse(date));
let format = new Intl.DateTimeFormat('default', options).format(newDate);
return format;
}
handleChange = event => {
this.setState({ searchCriteria: event.target.value });
};
renderList() {
let tournmentsArray = this.props.tournaments;
const filterTournaments = tournmentsArray.filter(item =>
item.name.includes(this.state.searchCriteria)
);
if (filterTournaments === undefined || filterTournaments.length === 0) {
return (
<React.Fragment>
<div className="notFound">
Something went wrong.
<br />
<button
className="notFoundButton"
onClick={() => {
this.setState({ searchCriteria: '' });
}}
>
Retry
</button>
</div>
</React.Fragment>
);
} else {
return filterTournaments.map(item => (
<Item
key={item.name}
name={item.name}
organizer={item.organizer}
participants={Object.values(item.participants)}
game={item.game}
start={this.formatDate(item.startDate)}
>
<div className="buttonBar">
<EditTournament id={item.id} />
<button
className="button"
onClick={() => {
if (
window.confirm('Are you sure you want to delete this item?')
) {
this.handleDelete(item.id);
}
}}
>
Delete
</button>
</div>
</Item>
));
}
}
render() {
return (
<div className="container">
<input
onChange={this.handleChange}
className="input"
placeholder="Search..."
id="searchField"
value={this.state.searchCriteria}
/>
<div className="row">{this.renderList()}</div>
</div>
);
}
}
function mapStateToProps({ tournaments }) {
return {
tournaments: Object.values(tournaments).flat()
};
}
export default connect(mapStateToProps, {
fetchTournaments
})(SearchAndDisplay);
与删除创建和编辑数据不同,它由redux处理,如下所示:
创建比赛:
import { reduxForm, Field } from 'redux-form';
import '../styles/promptForms.css';
import '../styles/Header.css';
import { connect } from 'react-redux';
import { createTournaments } from '../actions/tournaments';
class CreateTournamentPromptFrom extends React.Component {
constructor(props) {
super(props);
this.state = {
showHide: false
};
}
createTournamentButton() {
return (
<div>
<button
className="genericButton"
onClick={() => this.setState({ showHide: true })}
>
CREATE TOURNAMENT
</button>
</div>
);
}
renderInput = ({ input, label }) => {
return (
<div>
<label>{label}</label>
<br />
<input className="promptInput" {...input} autoComplete="off" />
</div>
);
};
onSubmit = formValues => {
this.props.createTournaments(formValues);
};
render() {
const { showHide } = this.state;
return (
<React.Fragment>
<div className={`overlay ${showHide ? 'toggle' : ''} `} />
<div className={`promptBox ${showHide ? 'toggle' : ''} `}>
<h3>localhost:3000 says</h3>
<form onSubmit={this.props.handleSubmit(this.onSubmit)}>
<Field
name="name"
component={this.renderInput}
label="Enter Tournament:"
/>
<button className="okayButton">OK</button>
</form>
<button
className="cancelButton"
onClick={() => this.setState({ showHide: false })}
>
Cancel
</button>
</div>
{this.createTournamentButton()}
</React.Fragment>
);
}
}
const formWrapped = reduxForm({
form: 'promptForm'
})(CreateTournamentPromptFrom);
export default connect(null, { createTournaments })(formWrapped);
动作:
import {
FETCH_TOURNAMENTS,
FETCH_TOURNAMENT,
CREATE_TOURNAMENT,
EDIT_TOURNAMENT
} from './types';
import { API_TOURNAMENTS_URL } from '../constants/api';
import axios from 'axios';
export const fetchTournaments = () => async dispatch => {
const response = await axios.get(API_TOURNAMENTS_URL);
dispatch({
type: FETCH_TOURNAMENTS,
payload: response.data.flat()
});
};
export const fetchTournament = id => async dispatch => {
const response = await axios.get(`http://localhost:4000/tournaments/${id}`);
dispatch({ type: FETCH_TOURNAMENT, payload: response.data });
};
export const createTournaments = formValues => async dispatch => {
const response = await axios.post(API_TOURNAMENTS_URL, {
...formValues
});
dispatch({ type: CREATE_TOURNAMENT, payload: response.data });
};
export const editTournaments = (id, formValues) => async dispatch => {
const response = await axios.patch(
`http://localhost:4000/tournaments/${id}`,
formValues
);
dispatch({ type: EDIT_TOURNAMENT, payload: response.data });
};
减速器:
import _ from 'lodash';
import {
FETCH_TOURNAMENT,
CREATE_TOURNAMENT,
FETCH_TOURNAMENTS,
EDIT_TOURNAMENT,
DELETE_TOURNAMENT
} from '../actions/types';
export default (state = {}, action) => {
switch (action.type) {
case FETCH_TOURNAMENT:
return { ...state, [action.payload.id]: action.payload };
case FETCH_TOURNAMENTS:
return { ...state, [action.payload.id]: action.payload };
case CREATE_TOURNAMENT:
return { ...state, [action.payload.id]: action.payload };
case EDIT_TOURNAMENT:
return { ...state, [action.payload.id]: action.payload };
case DELETE_TOURNAMENT:
return _.omit(state, action.payload);
default:
return state;
}
};
答案 0 :(得分:1)
这里是使用forceUpdate()
的方法(因为您不想使用状态):
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor() {
super();
this.items = [
{id: 1, name: "item 1"},
{id: 2, name: "item 2"},
];
this.handleDelete = this.handleDelete.bind(this);
}
handleDelete(index) {
const newState = [...this.items];
delete newState[index];
// or
// newState.splice(index, 1);
this.items = newState;
this.forceUpdate();
}
render() {
return (
<div>
{
this.items.map((item, index) => {
return (
<div>
{item.name}
<button onClick={() => this.handleDelete(index)}>Delete item</button>
</div>
)
})
}
</div>
);
}
}
render(<App />, document.getElementById('root'));
只需在map方法中传递索引:
...map((item, index) => ...);
在axios调用后在then()
中进行操作。
请注意,文档强烈建议您在可能的情况下避免使用forceUpdate()
,因此您确实应该为此使用状态,我看不出有任何好的理由不这样做在这里使用它。
答案 1 :(得分:1)
要“乐观地”从状态中删除项目,您需要立即从状态中删除该项目以立即在UI中反映更改。 但 ,您将需要添加额外的redux状态,以“保留”后端的待删除操作。删除成功后,清除保留的删除,如果删除失败,则清除保留的删除并将其重新添加到常规数据中(并可能显示一些错误消息或吐司等。)。
我看到您没有通过redux进行删除,因此请使用本地组件状态,并且在渲染时必须过滤锦标赛数据。
class SearchAndDisplay extends PureComponent {
componentDidMount() {
this.props.fetchTournaments();
}
state = {
searchCriteria: "",
isLoading: false,
optimisticTournaments: null // <-- state to hold temp "deleted" data
};
handleChange = event => {
this.setState({
searchCriteria: event.target.value
});
};
async handleDelete(id) {
console.log("delete id", id);
// optimistically remove element
this.setState({
optimisticTournaments: this.props.tournaments.filter(
item => item.id !== id
)
});
await axios
.delete(url + id)
.then(res => {
console.log(res.data);
// Need to create a call back to let parent know element was deleted
this.props.deleteSuccess(id);
})
.catch(err => {
console.log(err);
alert("Failed to delete");
})
.finally(() => {
this.setState({ optimisticTournaments: null });
});
}
formatDate(date) {
let options = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
hour12: false
};
let newDate = new Date(Date.parse(date));
let format = new Intl.DateTimeFormat("default", options).format(newDate);
return format;
}
handleChange = event => {
this.setState({ searchCriteria: event.target.value });
};
renderList() {
let tournmentsArray =
this.state.optimisticTournaments || this.props.tournaments;
const filterTournaments = tournmentsArray.filter(item =>
item.name.includes(this.state.searchCriteria)
);
if (filterTournaments === undefined || filterTournaments.length === 0) {
return (
<React.Fragment>
<div className="notFound">
Something went wrong.
<br />
<button
className="notFoundButton"
onClick={() => {
this.setState({ searchCriteria: "" });
}}
>
Retry
</button>
</div>
</React.Fragment>
);
} else {
return filterTournaments.map(item => (
<Item
key={item.name}
name={item.name}
organizer={item.organizer}
participants={Object.values(item.participants)}
game={item.game}
start={this.formatDate(item.startDate)}
>
<div className="buttonBar">
<EditTournament id={item.id} />
<button
className="button"
onClick={() => {
if (
window.confirm("Are you sure you want to delete this item?")
) {
this.handleDelete(item.id);
}
}}
>
Delete
</button>
</div>
</Item>
));
}
}
render() {
return (
<div className="container">
<input
onChange={this.handleChange}
className="input"
placeholder="Search..."
id="searchField"
value={this.state.searchCriteria}
/>
<div className="row">{this.renderList()}</div>
</div>
);
}
}