我有一个简单的ToDo应用,其中包含一些组件。我要做的就是共享状态并更新上下文数据。我可以用props来做,但是将来,如果我有更多的组件,那么用props传递数据将太麻烦了。这是我的代码...
MainContext.js
import React, { createContext, useState } from "react";
const MainContext = createContext([{}, () => {}]);
const MainContextProvider = (props) => {
const [state, setState] = useState({ title: "", body: "" });
return (
<MainContext.Provider value={[state, setState]}>
{props.children}
</MainContext.Provider>
);
};
export { MainContext, MainContextProvider };
App.js
import MainContent from "./MainContent";
import { MainContextProvider } from "./MainContext";
export default class App extends Component {
constructor() {
super();
this.state = {
};
}
render() {
return (
<div className="container">
<MainContextProvider>
<Nav navigationItems={this.state.navItems} />
<MainContent />
<Footer />
</MainContextProvider>
</div>
);
}
}
MainContent.js
import React, { Component } from "react";
import CardType from "./CardType";
import FormData from "./FormData";
class MainContent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
initialCounter: 0,
endCounter: 10,
showLoadMore: true,
cards: [],
};
}
DeleteCard = (cardId) => {
console.log(cardId);
this.setState((prevState) => {
const newCardArray = prevState.cards.filter((card) => card.id !== cardId);
return {
cards: newCardArray,
};
});
};
AddCard = (formData) => {
this.setState((prevState) => {
const newCardData = {
id: prevState.cards[prevState.cards.length - 1].id + 1,
userId: 12,
title: formData.title,
body: formData.description,
};
return {
cards: [...prevState.cards, newCardData],
// update the number of posts to +1
endCounter: prevState.endCounter + 1,
};
});
};
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => response.json())
.then((json) => {
this.setState({ isLoading: false, cards: json });
});
}
render() {
if (this.state.isLoading) {
return <h1>Loading....</h1>;
} else {
const cardsShow = this.state.cards.map((card) => {
return (
<CardType
key={card.id}
cardData={card}
deleteCard={this.DeleteCard}
/>
);
});
return (
<main className="jumbotron">
<h1>ToDo</h1>
<FormData data={this.AddCard} />
{cardsShow
.reverse()
.slice(this.state.initialCounter, this.state.endCounter)}
{this.state.showLoadMore ? (
<button
onClick={() => {
this.setState((prevState) => {
const newEndCounter = prevState.endCounter + 10;
const showLoadButton =
prevState.cards.length > newEndCounter ? true : false;
return {
endCounter: newEndCounter,
showLoadMore: showLoadButton,
// initialCounter: prevState.initialCounter + 10,
};
});
}}
>
Load More
</button>
) : null}
</main>
);
}
}
}
export default MainContent;
CardType.js
import React, { useContext, useEffect } from "react";
import { MainContextProvider } from "./MainContext";
const CardType = (props) => {
const [formData, setFormData] = useContext(MainContext);
const updateValues = (card) => {
setFormData(() => {
return {
title: card.title,
body: card.body,
};
});
};
return (
<div className="card">
<div className="card-body">
<h1>{props.cardData.title}</h1>
<p className="card-text">{props.cardData.body}</p>
<button onClick={() => props.deleteCard(props.cardData.id)}>
Delete
</button>
<button onClick={() => updateValues(props.cardData)}>Update</button>
</div>
</div>
);
};
export default CardType;
FormData.js
import React, { useState, useContext } from "react";
import { MainContextProvider } from "./MainContext";
const FormData = (props) => {
const [formData, setFormData] = useContext(MainContext);
const [title, setTitle] = useState(formData.title);
const [description, setDescription] = useState("formData.body);
const handleSubmit = (e) => {
e.preventDefault();
props.data({ title: title, description: description });
setTitle("");
setDescription("");
};
return (
<form>
<div className="form-group">
<label>Name</label>
<input
className="col-sm-12"
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</div>
<div className="form-group">
<label>Description</label>
<textarea
className="col-sm-12"
name="cardDescription"
value={description}
onChange={(e) => {
setDescription(e.target.value);
}}
/>
</div>
<p>{description}</p>
<button onClick={(e) => handleSubmit(e)}>Add</button>
</form>
);
};
export default FormData;
我想要的是,当我单击每个待办事项的“更新”按钮时,我的表单应填充选定的待办事项数据并更新上下文,并在保存时将上下文更新回空字符串。我是React的新手。如果没有其他使用上下文的替代方法,请分享。
答案 0 :(得分:2)
来自useContext
文档:
不要忘记useContext的参数必须是上下文 对象本身:
- 正确:
useContext(MyContext)
- 不正确:
useContext(MyContext.Consumer)
- 不正确:
useContext(MyContext.Provider)
因此,在您的代码示例中,替换此行
const [formData, setFormData] = useContext(MainContextProvider);
使用
const [formData, setFormData] = useContext(MainContext);
为防止将来出现类似错误,您可以制作包装器挂钩以访问上下文。
在 MainContext.js
中const useMainContext = () => useContext(MainContext)
现在您可以在任何此类功能组件中使用它们
const [formData, setFormData] = useMainContext();