useContext возвращает неопределенные значения

Столкнувшись с этой проблемой, когда мой контекст возвращает неопределенные значения, все, что он возвращает, - это начальное состояние. Здесь, в списке транзакций, я пытаюсь вызвать функцию deleteTransaction, которую я определил, но выдает ошибку, которая не определена. Скажите, пожалуйста, мне что-то не хватает или нужно что-то добавить.

Это мои иждивенцы, на всякий случай.

"dependencies": {
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^12.8.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.1"
},

GlobalState.js:

import React, { createContext, useReducer } from 'react'
import AppReducer from './AppReducer'

const initialState = {
transactions: [
    {id:1, text:"Flower", amount:-20},
    {id:2, text:"Salary", amount:300},
    {id:3, text:"Book", amount:-10},
    {id:4, text:"Camera", amount:150}
]
}

export const GlobalContext = createContext(initialState)

export const GlobalProvider = (props) => {
const [state, dispatch] = useReducer(AppReducer, initialState)

const deleteTransaction = (id) => {
    dispatch({type:'DELETE_TRANSACTION', payload:id})
}

return (<GlobalContext.Provider value={{transactions:state.transactions, deleteTransaction}}>
    {props.children}
</GlobalContext.Provider>)
}

AppReducer.js:

export default (state, action) => {
switch(action.type) {
    case 'DELETE_TRANSACTION':
        return {
            ...state,
            transactions: state.transactions.filter(transaction => transaction.id !== action.payload)
        }
    default:
        return state
}
}

TransactionList.js:

import React, { useContext } from 'react'
import { GlobalContext } from '../context/GlobalState'
import { Transaction } from './Transaction'

export const TransactionList = () => {

const { transactions } = useContext(GlobalContext)

return (
    <>
        <h3>History</h3>
        <ul className="list">
            {transactions.map(transaction => (
                <Transaction key={transaction.id} {...transaction} />
            ))}
        </ul>
    </>
)
}

Transaction.js:

import React, { useContext } from 'react'
import { GlobalContext } from '../context/GlobalState'

export const Transaction = ({id, text, amount}) => {

const {deleteTransaction} = useContext(GlobalContext)

const sign = amount < 0 ? "-" : "+"

return (
    <div>
        <li className={amount < 0 ? "minus" : "plus"}>
            {text} <span>{sign}${Math.abs(amount)}</span><button onClick={() => 
deleteTransaction(id)} className="delete-btn">x</button>
        </li>
    </div>
)
}

person Ammar Shoaib    schedule 07.04.2021    source источник
comment
Вам нужно обернуть свой компонент GlobalProvider там, где вы хотите использовать контекст   -  person Shravan Dhar    schedule 07.04.2021
comment
Входит ли ваш GlobalProvider в родительскую иерархию компонента TransactionList   -  person Shubham Khatri    schedule 07.04.2021
comment
Такая глупая ошибка. Я не так разбираюсь в React, но я не знаю, как забыл завершить его своим GlobalProvider. Спасибо за уделенное время. Теперь все работает.   -  person Ammar Shoaib    schedule 07.04.2021


Ответы (1)


Проблема

В вашем значении контекста по умолчанию отсутствует функция deleteTransaction.

const initialState = {
  transactions: [
    {id:1, text:"Flower", amount:-20},
    {id:2, text:"Salary", amount:300},
    {id:3, text:"Book", amount:-10},
    {id:4, text:"Camera", amount:150}
  ]
}

export const GlobalContext = createContext(initialState)

Решение

Определите форму значения по умолчанию для вашего контекста, чтобы она соответствовала тому, что используется компонентами, и убедитесь, что Transaction имеет GlobalContext.Provider над ним в дереве React.

const defaultValue = {
  transactions: [],
  deleteTransaction: () => {}, // <-- add a deleteTransaction function
}

export const GlobalContext = createContext(defaultValue);

Обновление контекста из вложенного компонента

Часто бывает необходимо обновить контекст из компонента, который находится где-то глубоко в дереве компонентов. В этом случае вы можете передать функцию вниз по контексту, чтобы позволить потребителям обновить контекст.

theme-context.js

// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},
});
person Drew Reese    schedule 07.04.2021
comment
Это не initialState контекста, это значение, которое используется, если в иерархии нет Provider - person Shubham Khatri; 07.04.2021
comment
@ShubhamKhatri OP назвал это начальным состоянием, я просто изначально использовал то же имя, что и они, но вы правы, createContext принимает значение по умолчанию. - person Drew Reese; 07.04.2021