上下文API无法正确传递数据

我正在尝试学习React的钩子,并且提供程序将其数据传递给我的组件的方式存在一些问题。

我有AuthContex,UsersContext,LanguagesContext和WordsContext。

ReactDOM.render(
  <React.StrictMode>
    <AuthProvider>
      <UsersProvider>
        <LanguagesProvider>
          <WordsProvider>
            <App />
          </WordsProvider>
        </LanguagesProvider>
      </UsersProvider>
    </AuthProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

AuthContext和UsersContext很好。

当我尝试调用getWord()时,WordsContext可以正确返回其状态,但会引发“ TypeError:getWord不是函数”。

尽管我的语言值设置为“ English”,但我尝试使用“ language”时,LanguagesContext返回“ undefined”,并且在调用getLanguage()时也会抛出“ TypeError”。

为了使其更直观:

export const Languages = () => {

  const { getLanguage, language } = useContext(LanguagesContext)
  const { getWord, word } = useContext(WordsContext)
  const { getUser, user } = useContext(UsersContext)

  const token = localStorage.getItem('token')
  const userId = localStorage.getItem('id')

  useEffect(() => {
    getUser(token, userId) // Works fine
    getWord(token, 1) // throws TypeError: getWord is not a function
    getLanguage(token, 1) // throws TypeError: getLanguage is not a function
  }, []);

  return (
    <div>
      {user ? user.name : null} {/* Works fine */} 

      {language} {/* Returns undefined despite being set to "English" in state */} 

      {word} {/* Returns state value but getWord() throws an error */} 
    </div>
  )
}

我猜这些函数会抛出错误,因为它们都从上下文中以“未定义”的形式返回,但是我完全不知道什么会导致此问题。

WordsContext:

const initialState = {
  word: 'Example',
  errors: null
}

export const WordsContext = createContext(initialState)

const port = 'http://127.0.0.1:8000'

const version = 'v1'

export const WordsProvider = ({ children }) => {
  const [state, dispatch] = useReducer(WordsReducer, initialState)

  async function getWord(token, word_id) {
    const config = {
      headers: {
        'Content-Type': 'application/json',
        "Authorization": token
      }
    }

    try {
      const res = await axios.get(`${port}/${version}/words/${word_id}`, config)

      dispatch({
        type: GET_WORD,
        payload: res.data
      })
    } catch (err) {
      dispatch({
        type: FAIL,
        payload: err
      })
    }
  }

  return (<LanguagesContext.Provider value={{
    word: state.word,
    erros: state.errors,
    getWord,
  }}>
    {children}
  </LanguagesContext.Provider>)
}

语言上下文:

const initialState = {
  language: 'English',
  errors: null
}

export const LanguagesContext = createContext(initialState)

const port = 'http://127.0.0.1:8000'

const version = 'v1'

export const LanguagesProvider = ({ children }) => {
  const [state, dispatch] = useReducer(LanguagesReducer, initialState)

  async function getLanguage(token, languageId) {
    const config = {
      headers: {
        'Content-Type': 'application/json',
        "Authorization": token
      }
    }

    try {
      const res = await axios.get(`${port}/${version}/languages/${languageId}`, config)

      dispatch({
        type: GET_LANGUAGE,
        payload: res.data
      })
    } catch (err) {
      dispatch({
        type: FAIL,
        payload: err
      })
    }
  }

  return (<LanguagesContext.Provider value={{
    language: state.language,
    erros: state.errors,
    getLanguage,
  }}>
    {children}
  </LanguagesContext.Provider>)
}
评论
  • R幻影
    R幻影 回复

    You have mistakenly used LanguagesContext.Provider instead of WordsContext.Provider in your WordsProvider which causes the conflict with LanguagesContext and because of that WordsContext also doesn't work

    export const WordsProvider = ({ children }) => {
      const [state, dispatch] = useReducer(WordsReducer, initialState)
    
      async function getWord(token, word_id) {
        const config = {
          headers: {
            'Content-Type': 'application/json',
            "Authorization": token
          }
        }
    
        try {
          const res = await axios.get(`${port}/${version}/words/${word_id}`, config)
    
          dispatch({
            type: GET_WORD,
            payload: res.data
          })
        } catch (err) {
          dispatch({
            type: FAIL,
            payload: err
          })
        }
      }
    
      return (
       <WordsContext.Provider value={{
        word: state.word,
        erros: state.errors,
        getWord,
      }}>
        {children}
      </WordsContext.Provider>
      )
    }