[英]Can't access context values in React
I'm trying to pass a value from one component within a context consumer to another component as a prop it says it's undefined
.我试图将一个值从上下文使用者中的一个组件传递给另一个组件作为道具,它说它是undefined
。
<ReadingSessionContext.Consumer>
{(context) => {
console.dir(context.state.session.duration) // Value is printed here
return (
...
<Timer duration={context.state.session.duration} />
...
)
}}
</ReadingSessionContext.Consumer>
And the Timer
component和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>
)
}
}
I've also tried to refactor this so that the Timer
component consumes the context, rather than passing it as a prop:我还尝试重构它,以便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);
});
}
In each case, the error that gets thrown is - Uncaught TypeError: Cannot read property 'split' of undefined
在每种情况下,抛出的错误都是 - Uncaught TypeError: Cannot read property 'split' of undefined
However, in every instance where I inspect the value before calling .split()
it tells me that the value exists, and is in fact correct, but all of a sudden stops existing as soon as I try to perform some action on the string但是,在调用.split()
之前检查值的每个实例中,它告诉我该值存在,并且实际上是正确的,但是一旦我尝试对字符串执行某些操作,它就会突然停止存在
Provider.jsx 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>
)
}
}
Context.jsx上下文.jsx
import React from "react";
const ReadingSessionContext = React.createContext();
export default ReadingSessionContext;
Okay.好的。 You're really close.你真的很亲近。 You still need to wrap your root component or hierachy with ReadingSessionProvider.您仍然需要使用 ReadingSessionProvider 包装您的根组件或层次结构。 So this is how it works generally.所以这就是它的一般工作方式。
const ReadingSessionContext = React.createContext();
你用const ReadingSessionContext = React.createContext();
创建上下文const ReadingSessionContext = React.createContext();
ReadingSessionProvider
class.您在创建ReadingSessionProvider
类时所做的工作。ReadingSessionProvider
wrap the app section you want to access the consumer.您使用ReadingSessionProvider
包装要访问使用者的应用程序部分。 So say所以说<ReadingSessionProvider>
<App />
</ReadingSessionProvider>
useContext(ReadingSessionContext)
or with ReadingSessionContext.Consumer
使用useContext(ReadingSessionContext)
或使用ReadingSessionContext.Consumer
See this video from Wes Bos for more information: https://youtu.be/XLJN4JfniH4有关更多信息,请参阅 Wes Bos 的此视频: https : //youtu.be/XLJN4JfniH4
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.