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.
<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
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:
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
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
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
import React from "react";
const ReadingSessionContext = React.createContext();
export default ReadingSessionContext;
console.logis not accurate ... when logging an object it'silently fixes'value when it is updated quickly ... in fact at start there is an empty object and on second render it's fetched object ... render Timer conditionally