Why setState does not change value? - reactjs

Why is below code not working?
It returns false even when I set inverted to true;
it also logs hit so it does reach.
import React, { useEffect, useState } from 'react';
import { ComponentProps } from 'react';
import { useHistory } from 'react-router-dom';
type Props = {
} & ComponentProps<'div'>;
export function HeaderMaster({
...props
}: Props) {
const [inverted, setInverted] = useState(false);
const history = useHistory()
useEffect(() => {
setInverted(true); // this does work
history.listen((location) => {
console.log(location.pathname);
if (location.pathname === '/bestellen') {
setInverted(true); // this does not
console.log('hit');
}
else {
setInverted(false);
}
})
},[history]);
useEffect(() => {
console.log(inverted);
},[inverted])
return (
<>
</>
);
}

Related

'TwitterProvider' cannot be used as a JSX component. Its return type 'void' is not a valid JSX element. how to fix it

I m getting error in TwitterProvider how to fix that
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { TwitterProvider } from '../context/TwitterContext'
import '../lib/hexStyles.css'
import React from 'react'
function MyApp({ Component, pageProps }: AppProps) {
return (
<TwitterProvider>
<Component {...pageProps} />
</TwitterProvider>
)
}
export default MyApp
error image
TwitterContext Code
import { createContext, useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { client } from '../lib/client'
export const TwitterContext = createContext()
export const TwitterProvider = ({ children }) => {
const [appStatus, setAppStatus] = useState()
const [currentAccount,setCurrentAccount] = useState('')
useEffect(() => {
checkIfWalletIsConnected()
}, [])
const checkIfWalletIsConnected = async () => {
if (!window.ethereum) return
try {
const addressArray = await window.ethereum.request({
method: 'eth_accounts',
})
if (addressArray.length > 0) {
setAppStatus('connected')
setCurrentAccount(addressArray[0])
} else {
router.push('/')
setAppStatus('notConnected')
}
}catch (error) {
console.log(error)
}
}
const connectToWallet = async () => {
if(!window.ethereum) return setAppStatus('noMetaMask')
try {
setAppStatus('loading')
const adressArray = await window.ethereum.request({
method: 'eth_requestAccounts',
})
if (addressArray.length > 0) {
setCurrentAccount(addressArray[0])
} else {
router.push('/')
setAppStatus('notConnected')
} catch (error) {
setAppStatus('error')
}
}
return (
<TwitterContext.Provider value={{appStatus, currentAccount,
connectToWallet }}
>
{children}
</TwitterContext.Provider>
)
}

Pass useRef() to grandchild component using typescript

Example code can be found below...
(Parent) App.tsx
import React, { useRef } from 'react';
import { Switch } from "react-router-dom";
import axios, { AxiosResponse } from 'axios';
import { AdminRoute } from './auth/protectedRoutes';
import Home from './views/Home';
export interface Data {
id: number;
name: string;
}
function App(): JSX.Element {
// variables
const searchDebouncerRef = useRef(false);
const [data, setData] = useRef<Array<Data>>([]);
// functions
async function updateData(searchString?: string | null) {
try {
const response: AxiosResponse<Array<Data>> = searchString
? await axios.get(`https://example.com/Api/Data$filter=contains(name, ${searchString})`)
: await axios.get('https://example.com/Api/Data');
if (searchDebouncerRef.current) {
return;
}
setData(response.data);
catch (e) {
console.log(e);
}
}
async function initData() {
try {
await updateData();
catch (e) {
console.log(e);
}
}
// setup
useEffect(() => {
initData();
}, []);
// render
return (
<>
<Switch>
<AdminRoute path="/">
<Home ref={searchDebouncerRef} updateData={updateData} data={data} />
</AdminRoute>
</Switch>
</>
)
}
export App;
(Child) Home.tsx
import React, { forwardRef } from 'react';
import { Data as DataRow } from '../App';
import Search from '../components/Search';
interface PROPS {
updateData: (searchString?: string | null) => void;
data: Array<DataRow>;
}
const Home: React.FC<any> = forwardRef(
({ updateData, data }: PROPS, ref) => {
return (
<div>
<Search isSearchDebouncingRef={ref} updateData={updateData} />
{data.map((row: DataRow) => ({
<p key={row.id}>{row.name}</p>
}))}
</div>
);
}
);
(Grandchild) Search.tsx
import React, { ChangeEvent, useCallback, useState } from 'react';
import { debounce } from 'lodash';
interface PROPS {
updateData: (searchString?: string | null) => void;
isSearchDebouncingRef: ???? // <-----------------------------------------------------
}
function Search({ updateData, isSearchDebouncingRef }: PROPS): JSX.Element {
// variables
const [searchText, setSearchText] = useState('');
const [searchDebouncerHasCompleted, setSearchDebouncerHasCompleted] = useState(false);
const searchDebouncer = useCallback(
debounce(() => {
setSearchDebouncerHasCompleted(true);
isSearchDebouncingRef.current = false;
}, 3000),
[]
);
// functions
function handleSearch(event: ChangeEvent<HTMLInputElement>) {
setSearchText(event.target.value);
isSearchDebouncingRef.current = true;
searchDebouncer();
}
// setup
useEffect(() => {
if (searchDebouncerHasCompleted) {
setSearchDebouncerHasCompleted(false);
updateData(searchText || null);
}
}, [searchDebouncerHasCompleted]);
// render
return <input type="text" value={searchText} onChange={(e) => handleSearch(e)} />; // ToDo: add icons(search, spinner, clear)
}
The grandchild file is where I am having trouble figuring out how to identify the type for the ref(see interface PROPS). Also the child file I would like to replace any, with the proper type if possible.

What is causing this enqueue snackbar error for notistack?

I'm trying to use the useSnack hook from notistack library but I keep getting this error
TypeError: Cannot destructure property 'enqueueSnackbar' of 'Object(...)(...)' as it is undefined.
Here is the code:
import React, { useContext, useEffect } from "react";
import AlertContext from "../context/alert/alertContext";
import { SnackbarProvider, useSnackbar } from "notistack";
const Alerts = (props) => {
const alertContext = useContext(AlertContext);
// This line below is where the error seems to be
const { enqueueSnackbar } = useSnackbar();
useEffect(() => {
alertContext.msg !== "" &&
enqueueSnackbar(alertContext.msg, {
variant: alertContext.type,
});
}, [alertContext]);
return <SnackbarProvider maxSnack={4}>{props.children}</SnackbarProvider>;
};
export default Alerts;
useSnackbar hook accessible anywhere down the tree from SnackbarProvider.
So you cannot use it in the same component as SnackbarProvier.
import AlertContext from "../context/alert/alertContext";
import { SnackbarProvider } from "notistack";
const Alerts = (props) => {
const alertContext = useContext(AlertContext);
const providerRef = React.useRef();
useEffect(() => {
alertContext.msg !== "" &&
providerRef.current.enqueueSnackbar(alertContext.msg, {
variant: alertContext.type,
});
}, [alertContext]);
return <SnackbarProvider ref={providerRef} maxSnack={4}>
{props.children}
</SnackbarProvider>;
};
export default Alerts;
Wrap you index file with SnapBar provider:
index.js
import { SnackbarProvider } from "notistack";
const Index = () => (
<SnackbarProvider maxSnack={1} preventDuplicate>
index
</SnackbarProvider>
)
export default Index
jsx file
import { useSnackbar } from "notistack";
const Logs = () => {
const { enqueueSnackbar } = useSnackbar();
const handler = () => {
enqueueSnackbar(`Successful.`, { variant: "success" });
};
return <span onClick={handler}>"Logs loading"</span>;
};
export default Logs;

call forwarding with history.push

I wrote here is the code
import React, { FC, Fragment, useEffect } from "react";
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
const HandlerErr: FC<{ error: string }> = ({ error }) => {
useEffect(()=>{
const time = setTimeout(() => {history.push(`/`)}, 2000);
return(()=> clearTimeout(time));
},[error])
return (
<Fragment>
<div>{error}</div>
<div>{"Contact site administrator"}</div>
</Fragment>
);
};
I use the HandlerErr component to redirect. but for some reason it doesn't work history.push (/).I took a video
You need to use history form the react-router-dom
like
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
class Test extends Component {
render () {
const { history } = this.props
return (
<div>
<Button onClick={() => history.push('./path')}
</div>
)
}
}
export default withRouter(Test)
import React, { FC, useEffect } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
interface OwnProps {
error: string;
}
type Props = OwnProps & RouteComponentProps<any>;
const HandlerErr: FC<Props> = ({ error, history }) => {
useEffect(() => {
const timeout = setTimeout(() => {
history.push(`/`);
}, 2000);
return () => {
clearTimeout(timeout);
};
}, [error]);
return (
<>
<div>{error}</div>
<div>Contact site administrator</div>
</>
);
};
export default withRouter(HandlerErr);

How to make forwarding react router 5

I am new to react and typescript.
I have a component Err.
I want to redirect it using react router 5 ?.
import React, { FC, Fragment, useEffect } from "react";
const Err: FC<{ error: string }> = ({ error }) => {
useEffect(()=>{
const time = setTimeout(() => {???(`/`)}, 2000);
return(()=> clearTimeout(time));
},[error])
return (
<Fragment>
<div>{error}</div>
<div>{"Contact site administrator"}</div>
</Fragment>
);
};
I don't know how to react router 5.
But if you use react router 4.
import React, { FC, Fragment, useEffect,useState } from "react";
import { Redirect } from "react-router";
const HandlerErr: FC<{ error: string }> = ({ error}) => {
const [booleURL, setBooleURL] = useState(false);
useEffect(()=>{
const time = setTimeout(() => {setBooleURL(true)}, 2000);
return(()=> clearTimeout(time));
},[error])
return (
<Fragment>
{ booleURL && <Redirect to="/"/>}
<div>{error}</div>
<div>{"Contact site administrator"}</div>
</Fragment>
);
};
or
import React, { FC, useEffect } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
interface OwnProps {
error: string;
}
type Props = OwnProps & RouteComponentProps<any>;
const HandlerErr: FC<Props> = ({ error, history }) => {
useEffect(() => {
const timeout = setTimeout(() => {
history.push(`/`);
}, 2000);
return () => {
clearTimeout(timeout);
};
}, [error]);
return (
<>
<div>{error}</div>
<div>Contact site administrator</div>
</>
);
};
export default withRouter(HandlerErr);

Resources