У меня есть три компонента. Сначала есть компонент EditableField, который я хочу переключать между показом тега h3 и вводом, в который пользователь может вводить больше текста (эта часть работает). Затем на OnBlur ввод должен измениться на h3 с обновленным текстом (также работает) и отправить внутренний запрос, чтобы сохранить новое значение h3 (эта часть не работает). EditableField отображается в компоненте Card, а компонент Card отображается в компоненте CardList, который содержит внутренние данные для массива карт.
У меня возникают трудности с определением 1), какой компонент должен управлять отправкой внутреннего запроса, чтобы сохранить новое текстовое значение? и 2) В зависимости от ответа на вопрос № 1, как я могу получить доступ к обновленному значению входного текста? Кроме того, я проверял в почтальоне, что мой текущий маршрут работает. Я опубликую это ниже после моих компонентов.
class EditableField extends Component {
constructor(props) {
super(props);
this.state = {
text: this.props.text
}
}
handleChange = (e) => {
this.setState({ text: e.target.value });
}
render() {
const { text } = this.state;
if(this.props.isEditing) {
return (
<input value={ text } type='text'
onChange={ this.handleChange }
onBlur={this.props.handleToggle} autoFocus />
)
}
return (
<h3 onClick={ this.props.handleToggle }
{text}
</h3>
)
}
}
export default EditableField;
class Card extends Component {
constructor(props) {
super(props);
this.state = {
isEditing: false
};
}
handleToggle = () => {
this.setState({ isEditing: !this.state.isEditing });
this.handleBlur(this.props._id, this.props.title);
// the above handleBlur does not work
}
handleBlur = async (id, text) => {
const res = await axios.put(`/api/surveys/${id}`, text);
}
render() {
const { isEditing } = this.state;
return (
<div className="col-sm-12 col-md-12 col-lg-6 my-3">
<div className="card">
<div className="card-body">
<div className="card-title">
<EditableField
text={this.props.title}
isEditing={isEditing}
handleToggle={this.handleToggle} />
</div>
</div>
</div>
</div>
)
}
}
export default Card;
export class CardList extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false
}
}
componentDidMount() {
this.props.fetchCards();
}
renderSurveys() {
return this.props.cards.reverse().map(({ _id, title, body, dateSent, yes, no}) => {
return (
<Card key={_id} title={title}
body={body} dateSent={dateSent}
yes={yes} no={no} _id={_id}
onDelete={ () => {
this.props.deleteSurvey(_id)
}} />
)
});
}
render() {
const { isLoading } = this.props;
return (
<div className="container">
{ isLoading && <LoadingIndicator /> }
<div className="row">
{this.renderSurveys()}
</div>
</div>
);
}
}
function mapStateToProps({ cards: { cards, isLoading }}) {
return {
cards,
isLoading
}
}
export default connect(mapStateToProps, { fetchCards, deleteCard })(CardList);
app.put('/api/surveys/:surveyId', async (req, res) => {
const { title } = req.body;
try {
await Survey.updateOne({ _id: req.params.surveyId }, {
$set: { title }
})
.exec();
res.send('ok').status(200);
}
catch(e) {
res.send(e).status(400);
}
});