#javascript #reactjs #typescript #error-handling
#javascript #reactjs #машинопись #обработка ошибок
Вопрос:
Я определил контекстную транзакцию, которая принимает объект и функцию. В транзакции AppProvider .Поставщик возвращается. Код взят из файла GlobalState.tsx:
import { createContext, useState } from "react";
export interface IProviderProps {
children?: any;
}
type Cat = {
id: number;
text: string;
amount: number;
}
type Ca =Cat[]
export const initialState = {
state: [
{id:4, text:'hi', amount:234},
{id:3, text:'hd', amount:-234},
{id:1, text:'hs', amount:34}
],
setState: (state: Ca) => {}
}
console.log(initialState.state)
export const Transaction = createContext(initialState);
export const AppProvider = (props: IProviderProps) => {
const [state, setState] = useState(initialState.state);
console.log(state);
return <Transaction.Provider value={{state, setState}}>{props.children}</Transaction.Provider>;
};
В App.tsx я передал провайдеру:
import React, { useState } from 'react';
import './App.css';
import { Header } from "./Components/Header";
import { Balance } from './Components/Balance';
import { IncomeExpense } from "./Components/Income_Expense";
import { TransactionHistory } from "./Components/TransactionHistory";
import { AddTransaction } from "./Components/AddTransaction";
import { AppProvider } from './Context/GlobalState'
function App() {
const [islit, setlit] = useState(true);
return (
<AppProvider>
<div className={`${islit? '': 'dark'} body`}>
<Header islit={islit} setlit={setlit} />
<div className="container">
<Balance />
<IncomeExpense />
<TransactionHistory />
<AddTransaction />
</div>
</div>
</AppProvider>
);
}
export default App;
Я пытаюсь изменить «состояние» на «setState», но оно не работает:
import React, { useState, useContext } from 'react';
import { Transaction} from '../Context/GlobalState';
export const AddTransaction = () => {
const initialState = useContext(Transaction);
const [Incexp, setIncExp] = useState('income');
const [text, settext] = useState('');
const [amount, setamount] = useState(0);
const transactions = initialState.state;
const settransaction = initialState.setState;
function Addition(e: any) {
e.preventDefault();
settext('');
setamount(0);
transactions.push({id:Math.floor(Math.random() * 100000000), text:text, amount:Incexp==='income'? amount: -amount})
settransaction(transactions);
console.log(transactions);
}
return (
<div>
<h3>Add Transaction</h3>
<form onSubmit={Addition}>
<label htmlFor="description">Text</label>
<input type="text" id="description" placeholder="Enter description..." value={text} onChange={(e) => { settext(e.target.value) }} required />
<label htmlFor="amount">Amount</label>
<input type="number" id="amount" placeholder="Enter Amount..." value={amount === 0 ? '' : amount} onChange={(e) => { setamount(parseInt(e.target.value)) }} required />
<div className="Inc-Exp">
<div>
<input type="radio" id="income" name="balance" defaultChecked onClick={()=>{setIncExp('income')}}/>
<label htmlFor="income" className="inc-col">Income</label>
</div>
<div>
<input type="radio" id="expense" name="balance" onClick={()=>{setIncExp('expense')}}/>
<label htmlFor="expense" className="exp-col">Expense</label>
</div>
</div>
<input className="btn" type="submit" value="Addtransaction" />
</form>
</div>
)
}
Другой дочерний компонент:
import React, { useContext } from 'react';
import { Transaction } from '../Context/GlobalState';
export const Balance = () => {
const initialState = useContext(Transaction);
const transactions = initialState.state;
var total=0;
transactions.map((transaction) => total =transaction.amount)
return (
<div>
<h4>Your Balance</h4>
<h1 className={`${total > 0 ? 'plus' : ''} ${total < 0 ? 'minus' : ''}`}>${total}</h1>
</div>
)
}
Каждый раз, когда я нажимаю на кнопку, добавляю транзакцию. Я хочу, чтобы он обновил состояние. но он не обновляется.
Комментарии:
1. Из того, что я понял, вы объявили
setState
как функцию, которая получает входные значения, но когда вы вызываете ее, вы, похоже, не используете ее как функцию. Ожидалось что-то вроде:initialState.setState(value_here)
. Пожалуйста, объясните, что вы пытаетесь сделать, и что пошло не так, и какую ошибку вы получаете2. Каждый раз, когда я нажимаю на кнопку, добавляю транзакцию. Я хочу, чтобы он обновил состояние. но он не обновляется.
3. какую ошибку вы получаете? выдается ошибка?
4. ошибка не выдается, я ошибочно ввел ее.
Ответ №1:
Состояние не обновляется, потому что вы не меняете ссылку на транзакции объекта, сделайте это, как показано ниже
function Addition(e: any) {
e.preventDefault();
settext('');
setamount(0);
settransaction([...transactions,{id:Math.floor(Math.random() * 100000000), text:text, amount:Incexp==='income'? amount: -amount} ]);
console.log(transactions);
}
В этом случае объект, который вы передаете settransaction, будет иметь новую ссылку, реакция обновит состояние
Ответ №2:
Пожалуйста, измените setState
на вариант обратного setState((previousState) => {...})
вызова как:
function Addition(e: any) {
e.preventDefault();
settext('');
setamount(0);
transactions.push({id:Math.floor(Math.random() * 100000000), text:text, amount:Incexp==='income'? amount: -amount})
settransaction(transactions);
console.log(transactions);
}
Для
function Addition(e: any) {
e.preventDefault();
settext('');
setamount(0);
settransaction((prevState) => {
return prevState.push({id:Math.floor(Math.random() * 100000000), text:text, amount:Incexp==='income'? amount: -amount});
});
}
console.log
Может не отображаться обновленное значение, так как для получения обновленного значения потребуется повторный рендеринг context
.
Но после context
обновления будет запущен повторный рендеринг react
, и, таким образом component
, ответственный за отображение обновленного state
, в конечном итоге отобразит обновленное состояние.
Комментарии:
1. Я попробовал это, но это выдает мне ошибку. Аргумент типа ‘(prevState: any) => any’ не может быть присвоен параметру типа ‘Ca’. В типе ‘(prevState: any) => any’ отсутствуют следующие свойства из типа ‘Cat[]’: pop, push, concat, join и еще 27.Параметр ts(2345) ‘prevState’ неявно имеет тип ‘any’. если я изменю prevState: any и в файле GlobalState.tsx (первый файл, который я упомянул), если я установлю setState: (state: any) => {} консоль. журнал дает мне число вместо массива объектов