Как правильно использовать новый React-хук useContext?

У меня есть некоторые трудности, чтобы понять новый способ использования реагирования Context API. У меня есть приложение с пользовательским классом Firebase. Теперь я хочу сделать крюк, чтобы передать его. До этого я использовал hok и context.

Мои вопросы

  1. Нужно ли использовать Hoc или это новый способ сделать это?
  2. Нужен ли мне Context.Provider или это новый Hook?
  3. Нужно ли объявлять значение по умолчанию как ноль, или я могу передать свой объект прямо из context.js
  4. Как я могу использовать новый Hook вместо Hok в моем коде?

Вот мой код с некоторыми комментариями, связанными с вопросами

// context.js this is my hoc
// index.jsx
import App from './App'
import Firebase, { FirebaseContext } from './components/Firebase'

const FirebaseContext = React.createContext(null)

export const withFirebase = Component => (props) => {
  // I don't need to wrap it to the FirebaseContext.Consumer
  // 1 But do I need this Hoc or it's a new way?
  const firebase = useContext(FirebaseContext)
  return <Component {...props} firebase={firebase} />
}

ReactDOM.render(
  // 2 Here I'm lost. Do I need the FirebaseContext.Provider or not?
  // 3 Do I need to declare value her or I should do it in context.js as a default?
  <FirebaseContext.Provider value={new Firebase()}>
    <App />
  </FirebaseContext.Provider>,
  document.getElementById('root'),
)

// App.jsx
// 4 Can I use a new Hook instead of Hok here and how?
import { withFirebase } from './components/Firebase/context'
const App = () => {
    const firebase = this.props.firebase // But should be useContext(FirebaseContext) or something like this?
    return(...)
}
export default withFirebase(App) // I don't need this with the Hook

Любая помощь приветствуется.

4 ответа

Решение

Вы должны сначала понять это, useContext просто использовать контекст и действует как потребитель, а не провайдер.

Ответить на ваши вопросы

Нужно ли использовать Hoc или это новый способ сделать это?

Вам не нужен HOC с крючками. Крючки предназначены для замены HOC и рендеринга реквизита.

Нужен ли мне Context.Provider или это новый Hook?

Не существует хуков, эквивалентных Context.Provider. Вы должны использовать его как есть.

Нужно ли объявлять значение по умолчанию как ноль, или я могу передать свой объект прямо из context.js

Значение по умолчанию для createContext используется только если вы не передаете value реквизит для Context.Provider, Если вы передадите его, значение по умолчанию будет проигнорировано.

Как я могу использовать новый Hook вместо Hok в моем коде?

Вместо того, чтобы использовать useContext в компоненте, возвращаемом HOC, используйте его непосредственно в компоненте

Образец кода

/ context.js this is my hoc
// index.jsx
import App from './App'
import Firebase, { FirebaseContext } from './components/Firebase'

const FirebaseContext = React.createContext(null)

ReactDOM.render(
  <FirebaseContext.Provider value={new Firebase()}>
    <App />
  </FirebaseContext.Provider>,
  document.getElementById('root'),
)

App.jsx

const App = () => {
    const firebase = useContext(FirebaseContext) 
    return(...)
}
export default App;
      import About from './About'
import React, { createContext, useContext, useState } from 'react'
import {colorThem} from '../App'

const listData =createContext()

const Home = () => {
    const [list , seTList]=useState([1,2,3,4,5,6,7,8,9])
    const data = useContext(colorThem)
  return (
    <div>
        <h1>I'm From Home {data}</h1>
        <listData.Provider value={list}>
        <About/>
        </listData.Provider>
    </div>
  )
}

export default Home
export {listData}


 import { useContext } from "react"
 import { listData } from "./Home"

const About = () => {
const arr = useContext(listData)
 console.log(arr)
  return (
    <div>
      <h1>About components </h1>
    {
        arr.map((item ,index)=><h1 key={index}>{item}</h1>)
    }
    </div>
  )
}

export default About

Вот протестированный код для useContext. В этом примере я обновляю данные формы и отображаю данные формы в другом компоненте.

      import React, {createContext, useReducer, useContext} from 'react';

// CREATING THE CONTEXT
const userContext = createContext(null);

// REDUCER FUNCTION FOR UPDATING THE CONTEXT
const reducerFn = (state = [], payload) => {
    switch (payload.type) {
        case 'FIRST_NAME':
            return {...state, formData: {firstName: payload.payload, lastName: state.formData.lastName}}
        case 'LAST_NAME':
            return {...state, formData: {firstName: state.formData.firstName, lastName: payload.payload}}
    
        default:
            return {...state};
    }
}

// CONTEXT PROVIDER COMPONENT TO PASS THE CONTEXT VALUE 
const AppContextProvider = ({children}) => {
    const [state, dispatch] = useReducer(reducerFn, {formData: {firstName: '', lastName: ''}});
    return(
        <userContext.Provider value={{state, dispatch}}>
            {children}
        </userContext.Provider>
    )
}

// ACTION CREATION 
const updateFname = (val) => {
    return {
        type: 'FIRST_NAME',
        payload: val
    }
}

const updateLname = (val) => {
    return {
        type: 'LAST_NAME',
        payload: val
    }
}
// ACTION CREATION 



// FORM COMPONENT AND UPDATING THE FORMDATA USING CONTEXT
const UserForm = () => {
    const {state, dispatch} = useContext(userContext)
    return (
        <>
            <div>
                <label htmlFor='fname'>First Name</label>
                <input type='text' id='fname' onChange={(e) => dispatch(updateFname(e.target.value))}/>
            </div>
            <div>
                <label htmlFor='lname'>Last Name</label>
                <input type='text' id='lname' onChange={(e) => dispatch(updateLname(e.target.value))}/>
            </div>
            
        </>
    )
}

// COMPONENT FOR DISPLAYING THE FORMDATA
const DisplayFormData = () => {
    const {state, dispatch} = useContext(userContext);
    return(
        <div>
            <p>First Name is : {state.formData.firstName} and last Name is {state.formData.lastName}</p>
        </div>
    )
}

// MAIN COMPONENT
function Question3Context(props) {
    return (
        <div>
            <AppContextProvider>
                <UserForm />
                <DisplayFormData />
            </AppContextProvider>
        </div>
    );
}

export default Question3Context;
  1. Нужно ли мне использовать HOC или это новый способ сделать это?

Нет, вам не нужно использовать HOC как лучший метод.

Почему? Начиная с React v7.0, вы можете использовать функциональные компоненты. Начиная с этой версии эффективно использовать новейшую технику под названием HOOKS, которая была разработана для замены класса и предоставления еще одной отличной альтернативы для компоновки поведения в ваших компонентах.


  1. Нужен ли мне Context.Provider или новый хук?

Хук типа useContext() имеет отношение к Context.Provider.
Контекст предназначен для обмена данными, которые можно считать «глобальными».

Компонент Provider принимает свойство value для передачи. Каждый контекст поставляется с провайдером.

Компонент Context.Provider, доступный в экземпляре контекста, используется для предоставления контекста его дочерним компонентам, независимо от того, насколько они глубоки.


  1. Нужно ли мне объявлять значение по умолчанию как нулевое или я могу передать свой объект прямо из context.js?

Нет, вам не обязательно объявлять значение по умолчанию.

Пример определения контекста в одном углу кодовой базы без defaultValue.

const CountStateContext = React.createContext() // <-- определяем контекст без defaultValue


  1. Как я могу использовать новый хук вместо HOC в своем коде?

index.jsx

      import App from './App'

import Firebase, { FirebaseContext } from './components/Firebase'

const FirebaseContext = React.createContext(null)

ReactDOM.render(
  <FirebaseContext.Provider value={new Firebase()}>
    <App />
  </FirebaseContext.Provider>,
  document.getElementById('root'),
)

Корневой компонент: App.js, где будут использоваться данные из контекста:

      const App = () => {
    const firebase = useContext(FirebaseContext) 
    return(...)
}
export default App;
Другие вопросы по тегам