我有一个返回两个组件的容器-一个用于添加新旅程的表单和一个用于列出所有旅程的表格。表单和表格都在同一页面上。
在表格中,我要添加一个可点击的单元格以编辑/删除旅程。虽然我可以删除给定的旅程,但是在尝试渲染表时,页面会在之后立即中断,因为其中一种旅程不再存在。
实现此功能的最佳方法是什么,当数据发生变化时,我可以从同一页面添加/编辑/删除旅程并用更新的数据刷新表?
journeysAdmin
容器:
class JourneysAdmin extends Component {
componentDidMount() {
this.props.onFetchJourneys(this.props.token, this.props.userId);
}
renderTableHeader() {
return (
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Description</TableCell>
<TableCell>Progress</TableCell>
<TableCell>Journey Points</TableCell>
<TableCell>Journey Status</TableCell>
</TableRow>
</TableHead>
);
}
render() {
let journeys = <Spinner />;
if (!this.props.loading) {
journeys = this.props.journeys.map(journey => (
<JourneyAdmin
key={journey._id}
journeyID={journey._id}
name={journey.name}
description={journey.description}
progress={journey.journeyPoints}
journeyPoints={journey.journeyPoints}
journeyStatus={journey.status}
journeyUserType={journey.journeyUserType}
isAuthenticated={this.props.user.isAuthenticated}
role={this.props.user.role}
lessons={journey.lessons}
journeyClicked={() =>
this.props.onJourneyClicked(
this.props.token,
journey._id,
this.props.userId
)
}
deleteJourney={() =>
this.props.onJourneyDeleted(journey._id, this.props.token)
}
/>
));
}
return (
<Paper>
<JourneyAdminForm
createjourney={(
journeyName,
journeyDescription,
journeyPoints,
journeyLevel,
journeyTime,
lessonName,
lessonShortDescription,
lessonDescription,
lessonExampleText
) =>
this.props.onAddJourney(
journeyName,
journeyDescription,
journeyPoints,
journeyLevel,
journeyTime,
lessonName,
lessonShortDescription,
lessonDescription,
lessonExampleText,
this.props.token
)
}
/>
<Table>
{this.renderTableHeader()}
{journeys}
</Table>
</Paper>
);
}
}
const mapStateToProps = state => {
return {
journeys: state.journey.journeys,
loading: state.journey.loading,
token: state.auth.token,
userId: state.auth.userId,
user: state.auth
};
};
const mapDispatchToProps = dispatch => {
return {
onFetchJourneys: (token, userId) =>
dispatch(actions.fetchJourneys(token, userId)),
onJourneyDeleted: (journeyID, token) =>
dispatch(actions.deleteJourney(journeyID, token)),
onAddJourney: (
journeyName,
journeyDescription,
journeyPoints,
journeyLevel,
journeyTime,
lessonName,
lessonShortDescription,
lessonDescription,
lessonExampleText,
token
) =>
dispatch(
actions.addJourney(
journeyName,
journeyDescription,
journeyPoints,
journeyLevel,
journeyTime,
lessonName,
lessonShortDescription,
lessonDescription,
lessonExampleText,
token
)
)
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(withErrorHandler(JourneysAdmin, axios));
journeysAdmin
表单组件:
class JourneyAdminForm extends Component {
state = {
controls: {
Name: {
elementType: "input",
elementConfig: {
placeholder: "Name"
},
value: "",
validation: {
required: true,
minLength: 8
},
valid: false,
touched: false
},
Description: {
elementType: "input",
elementConfig: {
placeholder: "Description"
},
value: "",
validation: {
required: true,
minLength: 8
},
valid: false,
touched: false
},
Points: {
elementType: "input",
elementConfig: {
placeholder: "Points"
},
value: "",
validation: {
required: true,
min: 100,
max: 999,
isNumeric: true
},
valid: false,
touched: false
},
Level: {
elementType: "input",
elementConfig: {
placeholder: "Level"
},
value: "",
validation: {
required: true,
minLength: 1
},
valid: false,
touched: false
},
journeyTime: {
elementType: "input",
elementConfig: {
placeholder: "Journey time"
},
value: "",
validation: {
minLength: 2,
isNumeric: true
},
valid: false,
touched: false
},
lessonName: {
elementType: "input",
elementConfig: {
placeholder: "Lesson Name"
},
value: "",
validation: {
required: true,
minLength: 8
},
valid: false,
touched: false
},
lessonShortDescription: {
elementType: "input",
elementConfig: {
placeholder: "Lesson short-description"
},
value: "",
validation: {
required: true,
minLength: 8
},
valid: false,
touched: false
},
lessonDescription: {
elementType: "input",
elementConfig: {
placeholder: "Lesson description"
},
value: "",
validation: {
required: true,
minLength: 8
},
valid: false,
touched: false
},
lessonExampleText: {
elementType: "input",
elementConfig: {
placeholder: "Lesson example text"
},
value: "",
validation: {
required: true,
minLength: 8
},
valid: false,
touched: false
}
}
};
checkValidity(value, rules) {
let isValid = true;
if (!rules) {
return true;
}
if (rules.required) {
isValid = value.trim() !== "" && isValid;
}
if (rules.minLength) {
isValid = value.length >= rules.minLength && isValid;
}
if (rules.maxLength) {
isValid = value.length <= rules.maxLength && isValid;
}
if (rules.isEmail) {
const pattern = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
isValid = pattern.test(value) && isValid;
}
if (rules.isNumeric) {
const pattern = /^\d+$/;
isValid = pattern.test(value) && isValid;
}
return isValid;
}
inputChangedHandler = (event, controlName) => {
let updatedControls = {
...this.state.controls,
[controlName]: {
...this.state.controls[controlName],
value: event.target.value,
valid: this.checkValidity(
event.target.value,
this.state.controls[controlName].validation
),
touched: true
}
};
this.setState({ controls: updatedControls });
};
submitHandler = event => {
event.preventDefault();
console.log("Create button on JourneyAdmin page was clicked");
this.props.createjourney(
this.state.controls.Name.value,
this.state.controls.Description.value,
this.state.controls.Points.value,
this.state.controls.Level.value,
this.state.controls.journeyTime.value,
this.state.controls.lessonName.value,
this.state.controls.lessonShortDescription.value,
this.state.controls.lessonDescription.value,
this.state.controls.lessonExampleText.value
);
};
render() {
const formElementsArray = [];
for (let key in this.state.controls) {
formElementsArray.push({
id: key,
config: this.state.controls[key]
});
}
let form = null;
form = formElementsArray.map(formElement => (
<Input
key={formElement.id}
elementType={formElement.config.elementType}
elementConfig={formElement.config.elementConfig}
value={formElement.config.value}
invalid={!formElement.config.valid}
shouldValidate={formElement.config.validation}
touched={formElement.config.touched}
changed={event => this.inputChangedHandler(event, formElement.id)}
/>
));
if (this.props.loading) {
form = <Spinner />;
}
let errorMessage = null;
if (this.props.status === "fail") {
errorMessage = <p>Journey could not be added because of errors!</p>;
} else if (this.props.status === "success") {
errorMessage = <p>New Journey has been created!!</p>;
}
return (
<div>
<form onSubmit={this.submitHandler}>
{form}
<button btnType="Success">Create</button>
</form>
{errorMessage}
</div>
);
}
}
export default JourneyAdminForm;
JourneysAdmin
表组件:
class JourneyAdmin extends Component {
handleEditClick = (id, column) => {
return event => {
console.log(`You will Edit row with id ${id}, Name: ${column}.`);
};
};
handleDeleteClick = (id, column) => {
return event => {
console.log(`You will delete on row with id ${id}, Name: ${column}.`);
this.props.deleteJourney(this.props.journeyID);
};
};
render() {
return (
<Aux>
<TableBody>
<TableRow key={this.props.journeyID}>
<TableCell>{this.props.journeyID}</TableCell>
<TableCell>{this.props.name}</TableCell>
<TableCell>{this.props.description}</TableCell>
<TableCell>{this.props.progress}</TableCell>
<TableCell>{this.props.journeyPoints}</TableCell>
<TableCell>{this.props.journeyStatus}</TableCell>
<TableCell
onClick={this.handleEditClick(
this.props.journeyID,
this.props.name
)}
>
EDIT
</TableCell>
<TableCell
onClick={this.handleDeleteClick(
this.props.journeyID,
this.props.name
)}
>
Delete
</TableCell>
</TableRow>
</TableBody>
</Aux>
);
}
}
export default JourneyAdmin;
答案 0 :(得分:0)
最后找到了问题。这不是在我的动作/减速器中正确添加/删除旅程。每次我向数据库添加旅程时,我都没有将它添加到状态中的journeys
对象,也没有从数据库中再次获取旅程以使更新后的列表进入状态。
类似地,在删除时,我执行完删除操作后并未获取旅程。因此状态未更新。
现在我正在做所有动作:
axios
.post(journeyjurl, newJourney)
.then(res => {
const addedJourney = [];
for (let key in res) {
addedJourney.push({
...res.data[key],
id: key
});
}
dispatch(addJourneySuccess(addedJourney[0].data));
})
在减速器中:
const addJourneysSuccess = (state, action) => {
return updateObject(state, {
journeys: state.journeys.concat(action.addedjourney),
loading: false
});
};
在“删除”操作中:
axios
.delete(journeyjurl)
.then(res => {
dispatch(deleteJourneySuccess());
dispatch(fetchJourneys(token, ""));
})
我还发现,从我要在其中调用添加/删除操作的容器/组件(例如:在fetchJourneys
中)调用handleDeleteClick
也是可以的。因此,在我上面的评论中,基本上是1和3。
希望这对以后像我这样的菜鸟有帮助!