使用React Hook,NO REDUX与其他组件共享API数据

时间:2020-02-12 11:39:07

标签: reactjs react-hooks


我正在尝试不使用任何状态管理工具(例如Redux)的Hooks,以通过使用类+ redux的传统结构来获得与我相同的行为/结构。

通常,使用类基本代码:

  • ComponentDidMount调度以调用API
  • 使用操作和化简器将数据存储在Redux中
  • 通过使用mapStateToProps将数据共享给我想要的任何组件

在这里问题出在使用不带Redux的钩子:“与任何组件共享数据”。

以下示例是我通过Hooks在组件之间共享状态的方式:

// app.js

import React, { useReducer } from 'react'
import { BrowserRouter } from 'react-router-dom'
import Routes from '../../routes'
import Header from '../Shared/Header'
import Footer from '../Shared/Footer'

export const AppContext = React.createContext();

// Set up Initial State
const initialState = {
  userType: '',
};

function reducer(state, action) {
  switch (action.type) {
    case 'USER_PROFILE_TYPE':
      return {
        userType: action.data === 'Student' ? true : false
      };
    default:
      return initialState;
  }
}

const App = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <BrowserRouter>
      <AppContext.Provider value={{ state, dispatch }}>
        <Header userType={state.userType} />
        <Routes />
        <Footer />
      </AppContext.Provider>
    </BrowserRouter>
  )
}

export default App

// profile.js

import React, { useEffect, useState, useContext} from 'react'
import { URLS } from '../../../constants'
import ProfileDeleteButton from './ProfileDeleteButton'
import DialogDelete from './DialogDelete'
import api from '../../../helpers/API';

// Import Context
import { AppContext } from '../../Core'

const Profile = props => {

  // Share userType State
  const {state, dispatch} = useContext(AppContext);
  const userType = type => {
    dispatch({ type: 'USER_PROFILE_TYPE', data: type }); <--- Here the action to call the reducer in the App.js file
  };

  // Profile API call
  const [ profileData, setProfileData ] = useState({});

  useEffect(() => {
    fetchUserProfile()
  }, [])

  const fetchUserProfile = async () => {
    try {
      const data = await api
        .get(URLS.PROFILE);
      const userAttributes = data.data.data.attributes;
      userType(userAttributes.type) <--- here I am passing the api response
    }
    catch ({ response }) {
      console.log('THIS IS THE RESPONSE ==> ', response.data.errors);
    }
  }
etc.... not important what's happening after this...

现在,我看到userType值的唯一方法是将其作为道具传递给<Header />组件。

// app.js

  <BrowserRouter>
    <AppContext.Provider value={{ state, dispatch }}>
      <Header userType={state.userType} /> <--passing here the userType as prop
      <Routes />
      <Footer />
    </AppContext.Provider>
  </BrowserRouter>

让我们说我想将userType的值传递给<Routes />的子级。 这里是一个例子:

<AppContext.Provider value={{ state, dispatch }}>
   <Routes userType={state.userType} />
</AppContext.Provider>

and then, inside <Routes /> ...

const Routes = () => 
  <Switch>
     <PrivateRoute exact path="/courses" component={Courses} userType={state.userType} /> 
  </Switch>

我不喜欢它。它不是干净,可持续或可扩展的。 关于如何使代码库更好的任何建议?

非常感谢 乔

2 个答案:

答案 0 :(得分:0)

您不需要将状态作为道具传递给每个组件。使用上下文,您可以访问父Provider的每个子组件中的化简器中的状态属性。就像您已经在Profile.js中完成

 const {state, dispatch} = useContext(AppContext);

这里的状态属性包含化简器中的状态属性。因此,您可以通过 state.userType

来访问它

答案 1 :(得分:0)

您需要的一切都在您的上下文之内。

我唯一要做的更改是传播数据,而不是一次尝试访问数据

<AppContext.Provider value={{ ....state, dispatch }}>

然后在您需要访问数据的组件内使用const context = useContext(AppContext)

context.userType