[英]Can't access context values in React
我試圖將一個值從上下文使用者中的一個組件傳遞給另一個組件作為道具,它說它是undefined
。
<ReadingSessionContext.Consumer>
{(context) => {
console.dir(context.state.session.duration) // Value is printed here
return (
...
<Timer duration={context.state.session.duration} />
...
)
}}
</ReadingSessionContext.Consumer>
和Timer
組件
class Timer extends React.Component {
state = {
"minutes": this.props.duration.split(":")[1].parseInt(), // Returns error here
"seconds": this.props.duration.split(":")[2].parseInt() // Returns error here
}
componentDidMount() {
console.dir(this.props) // Value is undefined here
this.myInterval = setInterval(() => {
const { seconds, minutes } = this.state;
if (seconds > 0) {
this.setState(({ seconds }) => ({
seconds: seconds - 1
}))
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(this.myInterval)
} else {
this.setState(({ minutes }) => ({
minutes: minutes - 1,
seconds: 59
}))
}
}
}, 1000)
}
render() {
const { minutes, seconds } = this.state;
return (
<Typography component="h1" variant="h5">
Time Remaining: { minutes }:{ seconds < 10 ? `0${ seconds }` : seconds }
</Typography>
)
}
}
我還嘗試重構它,以便Timer
組件使用上下文,而不是將其作為道具傳遞:
function Timer() {
const context = useContext(ReadingSessionContext);
const [minutes, setMinutes] = useState(3);
const [seconds, setSeconds] = useState(0);
useEffect(() => {
let duration = context.state.session.duration; // Value is accessable here
console.log(duration); // This logs to the console correctly, and it is a string
setMinutes(duration.split(":")[1].parseInt()); // Throws error here
setSeconds(duration.split(":")[2].parseInt()); // Throws error here
let timerInterval = setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(this.timerInterval)
} else {
setMinutes(minutes - 1);
setSeconds(59)
}
}
}, 1000);
});
}
在每種情況下,拋出的錯誤都是 - Uncaught TypeError: Cannot read property 'split' of undefined
但是,在調用.split()
之前檢查值的每個實例中,它告訴我該值存在,並且實際上是正確的,但是一旦我嘗試對字符串執行某些操作,它就會突然停止存在
Provider.jsx
import React from "react";
import axios from "axios";
import ReadingSessionContext from "./Context";
export default class ReadingSessionProvider extends React.Component {
/**
* Set the initial state of the `ReadingSessionProvider`
* @param {*} props
*/
state = {
"translationUrl": process.env.REACT_APP_BACKEND_URL + "translate/",
"readingSessionUrl": process.env.REACT_APP_BACKEND_URL + "reading-sessions/",
"session": {},
"book": {},
"translations": [],
"serverPage": 1,
"clientPage": 0,
"limit": 10,
"totalResults": 0,
"sessionId": 0,
"headers": {
"Content-type": "application/json",
"Authorization": "Token " + localStorage.getItem("token"),
}
}
/**
* After the component mounts, call the `getReadingSession` method
* and update the state with response
*/
async componentDidMount() {
let data = await this.getReadingSession();
this.setState({"session": data.data});
this.setState({"book": data.data.library_item.book});
await this.getTranslations()
}
/**
* Call the API and get data for this specific reading session
*/
async getReadingSession() {
let result = await axios.get(
this.state.readingSessionUrl + window.location.href.split('/')[5] + "/",
{headers: this.state.headers}
);
return result;
}
makeUrl = sessionId => {
return `${this.state.translationUrl}?page=${this.state.serverPage}&limit=${this.state.limit}&sessionId=${this.state.session.id}`;
}
/**
* Make the API call to the server to retrieve a list of the translations
* for the currently logged in user.
*/
getTranslations = async () => {
try {
let url = `${this.state.translationUrl}?page=${this.state.serverPage}&limit=${this.state.limit}&sessionId=${this.state.session.id}`
let response = await axios.get(url, {headers: this.state.headers});
await this.setState({"translations": response.data.results});
await this.setState({"totalResults": response.data.count});
} catch (error) {
console.log(error);
}
}
/**
* Submit the text that the user has input and get the updated
* list of translations from the API
*/
submitText = async (e, text) => {
console.log("hello?")
let data = {
"text_to_be_translated": text,
"session": this.state.session.id
};
try {
await axios.post(this.state.translationUrl, data, {headers: this.state.headers});
let paginationUrl = `${this.state.translationUrl}?page=${this.state.serverPage}&limit=${this.state.limit}&sessionId=${this.state.session.id}`;
this.getTranslations(paginationUrl);
} catch (error) {
console.dir(error);
}
}
setSessionId = sessionId => {
this.setState({"sessionId": sessionId});
console.log("called")
}
handleChangePage = async (event, newPage) => {
this.setState({"serverPage": newPage + 1})
this.setState({"clientPage": newPage})
let url = await `${this.state.translationUrl}translate/?page=${newPage + 1}&limit=${this.state.limit}&sessionId=${this.state.session.id}`
console.log(url)
await this.getTranslations(url);
}
render() {
return (
<ReadingSessionContext.Provider value={{
state: this.state,
getTranslations: this.getTranslations,
submitText: this.submitText,
handleChangePage: this.handleChangePage,
setSessionId: this.setSessionId,
makeUrl: this.makeUrl
}}>
{this.props.children}
</ReadingSessionContext.Provider>
)
}
}
上下文.jsx
import React from "react";
const ReadingSessionContext = React.createContext();
export default ReadingSessionContext;
好的。 你真的很親近。 您仍然需要使用 ReadingSessionProvider 包裝您的根組件或層次結構。 所以這就是它的一般工作方式。
const ReadingSessionContext = React.createContext();
創建上下文const ReadingSessionContext = React.createContext();
ReadingSessionProvider
類時所做的工作。ReadingSessionProvider
包裝要訪問使用者的應用程序部分。 所以說<ReadingSessionProvider>
<App />
</ReadingSessionProvider>
useContext(ReadingSessionContext)
或使用ReadingSessionContext.Consumer
有關更多信息,請參閱 Wes Bos 的此視頻: https : //youtu.be/XLJN4JfniH4
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.