簡體   English   中英

無法訪問 React 中的上下文值

[英]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 包裝您的根組件或層次結構。 所以這就是它的一般工作方式。

  1. 你用const ReadingSessionContext = React.createContext();創建上下文const ReadingSessionContext = React.createContext();
  2. 您可以使用它來創建上下文提供程序。 您在創建ReadingSessionProvider類時所做的工作。
  3. 您使用ReadingSessionProvider包裝要訪問使用者的應用程序部分。 所以說
<ReadingSessionProvider>
  <App />
</ReadingSessionProvider>
  1. 現在 App 組件的子組件可以使用在 ReadingSessionProvider 中設置的值。 使用useContext(ReadingSessionContext)或使用ReadingSessionContext.Consumer

有關更多信息,請參閱 Wes Bos 的此視頻: https : //youtu.be/XLJN4JfniH4

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM