Basically, the component's operation is to change the screen and click on the menu button, which has the same event mentioned in the test: somaTabsChange
However, when I run the test, it fails to change the DOM with the new elements.
Basically, this is log i get:
TestingLibraryElementError: Unable to find a label with the text of:
Criar menu
Test
it('should render the menu when save a modal', async () => {
getPageManagerInfo();
nock(env.SERVICE_URL)
.persist()
.post('/modules/cards/menu', {
name: 'menus',
icon: 'menus',
})
.reply(200, {
moduleMenu: {
pages: [],
_id: '61d33fd3b922dd0011ddc024',
icon: 'menus',
name: 'menus',
__v: 0,
},
});
const history = createMemoryHistory();
history.push('/manager/module/cards');
const renderResult = render(
<Router history={history}>
<Route path="/manager/module/:id" exact>
<PageManager />
</Route>
</Router>,
);
await changeTabs(renderResult, 'menus', 'menus');
await callModalForm({
render: renderResult,
buttonLabel: 'Criar menu',
buttonConfirmLabel: 'Salvar',
events: async () => {
await changeInput(renderResult, 'Nome', 'menus');
await changeInput(renderResult, 'Ícone', 'menus');
},
});
await callButton(renderResult, 'Fechar modal');
});
Component
import React, { useEffect, useState } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { SomaTab } from '#soma/react';
import { getModule } from 'services/ModuleService';
import Module from 'models/ModuleV2';
import LoaderFull from 'components/LoaderFull';
import ListPages from './container/ListPages';
import ListMenus from './container/ListMenus';
import { StyledTabs } from './styles';
const PageManager: React.FC = () => {
const history = useHistory();
const { id } = useParams<{ id: string }>();
const [loading, setLoading] = useState(true);
const [module, setModule] = useState<Module>();
const [tab, setTab] = React.useState<string>('pages');
const getData = async (): Promise<void> => {
const result = await getModule(id);
if (result.data) {
setModule(result.data);
} else {
history.push('/404');
}
setLoading(false);
};
useEffect(() => {
getData();
}, []);
if (loading) {
return <LoaderFull />;
}
return (
<>
<StyledTabs value={tab} onSomaTabsChange={e => setTab(e.detail)}>
<SomaTab value="pages">Páginas</SomaTab>
<SomaTab aria-label="menus" value="menus">
menus
</SomaTab>
</StyledTabs>
{tab === 'pages' ? (
<ListPages module={module!} onUpdate={getData} />
) : (
<ListMenus module={module!} onUpdate={getData} />
)}
</>
);
};
export default PageManager;
Related
I am getting the above error in my TypeScript code. I am attaching the codes of 2 files along with the error message. Please look into it.
This is the "NewPostForm.tsx" file in which error is occuring.
import React, { useState } from 'react';
import {AlertIcon, Flex, Icon, Alert, Text} from "#chakra-ui/react";
import {BiPoll} from "react-icons/bi";
import { BsLink45Deg, BsMic } from 'react-icons/bs';
import { IoDocumentText, IoImageOutline } from 'react-icons/io5';
import {AiFillCloseCircle, AiTwotoneWallet} from "react-icons/ai";
import TabItem from './TabItem';
import TextInputs from "./PostForm/TextInputs"
import { render } from 'react-dom';
import ImageUpload from './ImageUpload';
import { User } from 'firebase/auth';
import { useRouter } from 'next/router';
import { addDoc, collection, serverTimestamp, Timestamp, updateDoc } from 'firebase/firestore';
import { firestore, storage } from '../../firebase/clientApp';
import { getDownloadURL, ref, uploadString } from 'firebase/storage';
import { Post } from '../../atoms/postsAtom';
import useSelectFile from '../../hooks/useSelectFile';
type NewPostFormProps = {
user: User;
};
const formTabs = [
{
title: "Post",
icon: IoDocumentText,
},
{
title: "Images & Video",
icon: IoImageOutline,
},
{
title: "Link",
icon: BsLink45Deg,
},
{
title: "Poll",
icon: BiPoll,
},
{
title: "Talk",
icon: BsMic,
},
];
export type TabItem = {
title: string;
icon: typeof Icon.arguments;
};
const NewPostForm:React.FC<NewPostFormProps> = ({user}) => {
const router = useRouter();
const [selectedTab, setSelectedTab] = useState(formTabs[0].title);
const [textInputs, setTextInputs] = useState({
title: "",
body: "",
});
const {selectedFile, setSelectedFile, onSelectFile} = useSelectFile();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const handleCreatePost = async() => {
const {communityId} = router.query;
// Create new post object => type Post
const newPost: Post = {
communityId: communityId as string,
creatorId: user?.uid,
creatorDisplayName: user.email!.split("#")[0],
title: textInputs.title,
body: textInputs.body,
numberOfComments: 0,
voteStatus: 0,
createdAt: serverTimestamp() as Timestamp,
id: ''
};
setLoading(true);
try {
// Store the post in DB
const postDocRef = await addDoc(collection(firestore, "posts"), newPost);
// Check for selected file
if(selectedFile)
{
// Store in storage => getDownloadURL {return imageURL}
const imageRef = ref(storage, `posts/${postDocRef.id}/image`);
await uploadString(imageRef, selectedFile, "data_url");
const downloadURL = await getDownloadURL(imageRef);
// Update post doc by adding imageURL
await updateDoc(postDocRef, {
imageURL: downloadURL,
});
}
// redirect the user back to the communityPage using the router
router.back();
}
catch(error: any)
{
console.log("handleCreatePost error", error.message);
setError(true);
}
setLoading(false);
};
const onTextChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const {
target: {name, value},
} = event;
setTextInputs((prev) => ({
...prev,
[name]: value,
}));
};
return <div>
<Flex direction="column" bg="white" borderRadius={4} mt={2}>
<Flex width="100%">
{formTabs.map((item) => (
<TabItem key={item.title} item={item} selected={item.title === selectedTab}
setSelectedTab={setSelectedTab} />
))}
</Flex>
<Flex p={4}>
{selectedTab === "Post" && (
<TextInputs textInputs={textInputs} handleCreatePost={handleCreatePost}
onChange={onTextChange} loading={loading} />)}
{selectedTab === "Images & Video" && (
<ImageUpload
selectedFile={selectedFile}
onSelectImage={onSelectFile}
setSelectedTab={setSelectedTab}
setSelectedFile={setSelectedFile} />
)}
</Flex>
{error && (
<Alert status="error">
<AlertIcon />
<Text mr={2}>Error Creating the Post</Text>
</Alert>
)}
</Flex>
</div>
}
export default NewPostForm;
Also I am attaching another "useSelectFile.tsx" file for reference.
import React, {useState} from 'react';
const useSelectFile = () => {
const [selectedFile, setSelectedFile] = useState<string>();
const onSelectFile = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log("THIS IS HAPPENING", event);
const reader = new FileReader();
if(event.target.files?.[0])
{
reader.readAsDataURL(event.target.files[0]);
}
reader.onload = (readerEvent) => {
if(readerEvent.target?.result)
{
setSelectedFile(readerEvent.target.result as string);
}
};
};
return
{
selectedFile
setSelectedFile
onSelectFile
};
};
export default useSelectFile;
Also I am attaching the screenshot of error message.
You have newline after return, so you are not returning anything from your useSelectFile hook. Remove the line break in return statement:)
You have return nothing from your hook file and the return object you are expecting is wrong
Try this
return {
selectedFile,
setSelectedFile,
onSelectFile,
};
a working sandbox is here
I'm having the following problem with my react + nextJS project...
The component is something like this:
import React, { FC, useCallback, useEffect, useState } from 'react';
import InputMask, { Props } from 'react-input-mask';
import {
getPayersDetails,
PayerCompany,
PayerContact,
PayerDocuments,
} from 'services';
import { Formik } from 'formik';
import { Field, Loading, Page, Tooltip } from 'components';
import { Button, IconButton, Typography } from '#mui/material';
import { TextField, TextFieldProps } from '#material-ui/core';
import { SvgSelfCheckout } from 'images';
import {
FaEdit,
FaFileInvoiceDollar,
FaUserCheck,
FaUserAltSlash,
} from 'react-icons/fa';
import theme from 'styles/theme';
import * as S from './styles';
import { useRouter } from 'next/router';
import { PAYER_HOME } from 'src/routes';
const PayersDetails: FC = () => {
const [payerCompany, setPayerCompany] = useState<PayerCompany[]>([]);
const [payerContact, setPayerContact] = useState<PayerContact[]>([]);
const [payerDocument, setPayerDocument] = useState<PayerDocuments[]>([]);
const [loading, setLoading] = useState(true);
const [isActivePayer, setIsActivePayer] = useState(false);
const router = useRouter();
const getPayerDetails = useCallback(async (payerId: number) => {
setLoading(true);
const payerDetails = await getPayersDetails(payerId);
setPayerCompany(payerDetails.payerCompany);
setPayerDocument(payerDetails.payerDocument);
setPayerContact(payerDetails.payerContact);
setLoading(false);
}, []);
useEffect(() => {
if (!router.isReady) {
return;
}
const payerId = router.query.payerId as string;
try {
const safePayerId = parseInt(payerId);
getPayerDetails(safePayerId);
} catch (e) {
router.push(PAYER_HOME);
return;
}
}, [getPayerDetails, router]);
const contact = payerContact.length > 0 ? payerContact[0] : null;
const mobilePhone = payerContact
.filter(contact => contact.contactType.contactTypeName === 'mobile')
.map(contact => contact.value)[0];
return (
<Page
title="Detalhes do pagador"
pageTitle="Detalhes do pagador"
pageSubtitle="Dados pessoais"
pageSubitleColor={`${theme.palette.primary.light}`}
>
{loading ? (
<Loading show={loading} />
) : (
<Formik
enableReinitialize={true}
initialValues={{
name: contact?.contactName,
email: contact?.value,
}}
onSubmit={() => console.log('onSumit')}
>
....
)}
</Formik>
)}
</Page>
);
};
export default PayersDetails;
And I'm trying to test it with the following code:
import { render, screen, fireEvent } from '#testing-library/react';
import { getCompany } from 'services/companies';
import { getPayersDetails } from 'services/payers';
import PayersImport from '.';
import { useRouter } from 'next/router';
import userEvent from '#testing-library/user-event';
jest.mock('services/payers', () => ({
__esModule: true, // this property makes it work
default: 'mockedDefaultExport',
getPayersDetails: jest.fn(),
}));
jest.mock('next/router', () => ({
useRouter: jest.fn().mockImplementation(() => ({
route: '/',
pathname: '',
query: '',
asPath: '',
})),
}));
describe('payers details layout', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
describe('when rendering', () => {
let getPayersDetailsMock;
beforeEach(() => {
getPayersDetailsMock = {
...
};
getPayersDetails.mockResolvedValue(getPayersDetailsMock);
useRouter.mockImplementation(() => ({
route: '/',
pathname: '',
isReady: true,
query: { payerId: 1 },
asPath: '',
}));
render(<PayersImport />);
});
it('Calls details api with the correct id', () => {
expect(getPayersDetails).toHaveBeenCalledWith(1);
});
});
});
The issue is:
The component load ok when we go to a browser, but when I run it on jest I get the following error:
console.error
Warning: An update to PayersDetails inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at PayersDetails (/home/thiago/finnet/repos/welcome/apps/lunapay-front/src/layouts/Payers/PayersDetails/index.tsx:29:43)
43 | setPayerContact(payerDetails.payerContact);
44 |
> 45 | setLoading(false);
| ^
46 | }, []);
47 |
48 | useEffect(() => {
I get it is only a warning and it wouldn't be a problem for me, but the issue is that it goes into a infinite loop trying to render again.
What am I doing wrong??
I solved the issue, but it was not the best solution.
Basically the render was being triggered by the <Loading /> component being rendered again.
What I did was just adding a new property telling me if it was already fetched and canceling the loop.
const [payerDetailsResponse, setPayerDetailsResponse] =
useState<PayerDetailsResponse | null>(null);
const [payerCompany, setPayerCompany] = useState<PayerCompany[]>([]);
const [payerContact, setPayerContact] = useState<PayerContact[]>([]);
const [payerDocument, setPayerDocument] = useState<PayerDocuments[]>([]);
const [loading, setLoading] = useState(true);
const [isActivePayer, setIsActivePayer] = useState(false);
const router = useRouter();
const getPayerDetails = useCallback(async (payerId: number) => {
setLoading(true);
const payerDetails = await getPayersDetails(payerId);
setPayerDetailsResponse(payerDetails);
setPayerCompany(payerDetails.payerCompany);
setPayerDocument(payerDetails.payerDocument);
setPayerContact(payerDetails.payerContact);
setLoading(false);
}, []);
useEffect(() => {
if (payerDetailsResponse) {
return;
}
if (!router.isReady) {
return;
}
const payerId = router.query.payerId as string;
try {
const safePayerId = parseInt(payerId);
getPayerDetails(safePayerId);
} catch (e) {
router.push(PAYER_HOME);
return;
}
}, [router, getPayerDetails]);
Sorry not to be able to help more, but that was a solution for my problem :)
Sometimes jest fall into an infinite loop with useEffect, if that is your case, you can make a mock of it
import React from 'react'
const mockUseEffect = jest.fn()
jest.spyOn(React, 'useEffect').mockImplementation(mockUseEffect)
and try with that and/or adapt to your needs
I am working through a react app using v17. I have a component that adds an expense. The functionality in the component works as expected in the GUI but when I try to test it using jest/enzyme it throws an error of TypeError: Cannot read properties of undefined (reading 'find'). In the GUI it finds the expense I am trying to edit without issue. Am I not testing it correctly when trying to match a snapshot?
Edit Expense Component
import React from "react";
import { useParams } from "react-router-dom";
import { connect } from "react-redux";
import { ExpenseForm } from "./ExpenseForm";
import { editExpense, removeExpense } from "../actions/expenses";
//React router
import { useNavigate } from "react-router-dom";
export const EditExpensePage = (props) => {
const navigate = useNavigate();
const { expenseID } = useParams();
const foundExpense = props.expenses.find(
(expense) => expense.id === expenseID
);
return (
<div>
<h1>Edit Expense</h1>
<ExpenseForm
expense={foundExpense}
onSubmit={(expense) => {
// //Edit expense action expects 2 params (id, updates)
props.editExpense(expenseID, expense);
// //Redirect to dashboard
navigate("/");
}}
/>
<button
onClick={(e) => {
e.preventDefault();
props.removeExpense(expenseID);
navigate("/");
}}
>
Remove Expense
</button>
</div>
);
};
const mapStateToProps = (state, props) => ({
expenses: state.expenses
});
const mapDispatchToProps = (dispatch) => ({
editExpense: (id, expense) => dispatch(editExpense(id, expense)),
removeExpense: (id) => dispatch(removeExpense(id))
});
export default connect(mapStateToProps, mapDispatchToProps)(EditExpensePage);
Current Test
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let history, editExpense, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
Updated editExpense value in test
const setup = (props) => {
//editExpense = testExpenses[1]; //Same error
editExpense = jest.fn(); //Same error
let removeExpense = jest.fn();
let history = jest.fn();
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
Updated Test File
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let editExpense, expenseID, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
expenseID = 1;
editExpense = [testExpenses.find((expense) => expense.id === expenseID)];
console.log(editExpense);
//Output from this console log
// [
// {
// id: 1,
// description: 'Wifi payment',
// note: 'Paid wifi',
// amount: 10400,
// createdAt: 13046400000
// }
// ]
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
Updated your code
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let history, editExpense, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
editExpense = testExpenses; //it should be an array like this [{ id: 1 }]
const component = shallow(
<EditExpensePage
{...props}
expenses={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
Your EditExpensePage is calling props.expenses, but in your test cases, you never set it up.
You only introduce it here
let history, editExpense, removeExpense, wrapper;
but you haven't set the value for editExpense which means it's undefined.
That's why undefined.find throws an error.
I'd suggest you set a mocked value for editExpense.
I'm using socket.io along with react for a project. Here's my component
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { io } from 'socket.io-client';
import Button from '../../components/Button';
import { IProject } from '../../interfaces/projects';
import { IRun } from '../../interfaces/runs';
const socket = io(process.env.REACT_APP_SERVER_URL);
export default function RunAll() {
const { search } = useLocation();
// API State
const [project, setProject] = useState<IProject | undefined>(undefined);
const [runs, setRuns] = useState<IRun[]>([]);
// Query Params
const queryParams = new URLSearchParams(search);
const projectId = queryParams.get('projectId')!;
// Get Project
useEffect(() => {
(async () => {
const { data: project } = await axios.get(`${process.env.REACT_APP_SERVER_URL}/api/projects/${projectId}`);
setProject(project.data);
})();
}, [projectId]);
// Clear socket
useEffect(() => () => {
socket.close();
});
const runAllTests = async () => {
project?.tests.forEach((test) => {
console.log(test);
socket.emit('create run', { projectId, testId: test.id, url: process.env.REACT_APP_SERVER_URL });
});
socket.on('created run', (run: IRun) => {
console.log(run);
setRuns([...runs, run]);
});
};
console.log(runs);
const renderHeader = () => (
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', alignItems: 'center' }} className='mb-3'>
<h1 className='heading-primary mt-auto mb-auto'>Run Overview</h1>
<Button onClick={runAllTests}>Run All Tests</Button>
</div>
);
return (
<main>
{renderHeader()}
{runs?.map((run) => (
<div>{run.id}</div>
))}
</main>
);
}
When the button is click and runAllTests() is called, i can see the console.log(test) in the console and my server logs also show me that it has received the socket.emit('create run'). And when the server responds with socket.on('created run'), I can see the value of the created run. However, only the 2nd run(in case of the length of project.tests being 2), only the last run is being added to the state.
What am I missing here? Please help me out! Thanks in advance!
socket.on('created run', (run: IRun) => { console.log(run); setRuns([...runs, run]); });
use this code in useEffect and make sure it only runs once. Following should work for you.
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { io } from 'socket.io-client';
import Button from '../../components/Button';
import { IProject } from '../../interfaces/projects';
import { IRun } from '../../interfaces/runs';
const socket = io(process.env.REACT_APP_SERVER_URL);
export default function RunAll() {
const { search } = useLocation();
// API State
const [project, setProject] = useState<IProject | undefined>(undefined);
const [runs, setRuns] = useState<IRun[]>([]);
// Query Params
const queryParams = new URLSearchParams(search);
const projectId = queryParams.get('projectId')!;
// Get Project
useEffect(() => {
(async () => {
const { data: project } = await axios.get(`${process.env.REACT_APP_SERVER_URL}/api/projects/${projectId}`);
setProject(project.data);
})();
}, [projectId]);
// Clear socket
useEffect(() => () => {
socket.on('created run', (run: IRun) => {
console.log(run);
setRuns([...runs, run]);
});
return function cleanup () {
socket.close();
}
},[]);
const runAllTests = async () => {
project?.tests.forEach((test) => {
console.log(test);
socket.emit('create run', { projectId, testId: test.id, url: process.env.REACT_APP_SERVER_URL });
});
};
console.log(runs);
const renderHeader = () => (
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', alignItems: 'center' }} className='mb-3'>
<h1 className='heading-primary mt-auto mb-auto'>Run Overview</h1>
<Button onClick={runAllTests}>Run All Tests</Button>
</div>
);
return (
<main>
{renderHeader()}
{runs?.map((run) => (
<div>{run.id}</div>
))}
</main>
);
}
I am trying to implement Redirect from react-router-dom and it's redirecting in the URL, but not re-rendering the corresponding component.
import React, {useEffect, useState} from 'react';
import axios from 'axios';
import * as OnfidoSDK from 'onfido-sdk-ui/dist/onfido.min.js';
import 'onfido-sdk-ui/dist/style.css';
import {Redirect} from 'react-router-dom';
const onfidoContainerId = 'onfido-sdk-wrapper';
const transmitAPI = 'third/party/api/url';
const useOnfidoFetch = (URL) => {
const [token, setToken] = useState();
const [id, setId] = useState();
const [isClear, setIsClear] = useState(false);
useEffect(() => {
axios
.get("http://localhost:5000/post_stuff")
.then((response) => response.data.data.data.json_data)
.then((json_data) => {
console.log("this is the json data", json_data);
const id = json_data.applicant_id;
const token = json_data.onfido_sdk_token;
setId(id);
setToken(token);
});
}, [URL]);
useEffect(() => {
if (!token) return;
console.log("this is working!");
onfidoOut = OnfidoSDK.init({
token,
containerId: "root",
steps: [
{
type: "welcome",
options: {
title: "Open your new bank account",
},
},
"document",
],
onComplete: function (data) {
console.log("everything is complete");
console.log("this is the applicant id", id);
let obj;
axios
.post("http://localhost:5000/post_id", {
applicant_id: id,
})
.then((response) => {
obj = response.data.data.data.json_data.result;
setReceivedResults(obj === "clear");
});
if (setReceivedResults) {
onfidoOut.tearDown();
return <Redirect to="/result" />
} else {
return null;
}
},
});
}, [id, token]);
};
export default function() {
const URL = `${transmitAPI}/anonymous_invoke?aid=onfido_webapp`;
const result = useOnfidoFetch(URL, {});
return (
<div id={onfidoContainerId} />
)
}
I am not getting any errors in console. This is the App.js file with all of my components:
import Landing from './components/Landing';
import Onfido from './components/Onfido';
import Result from './components/Result';
export default () => {
return (
<div>
<StylesProvider>
<BrowserRouter>
<Switch>
<Route exact path="/onfido" component={Onfido} />
<Route exact path="/result" component={Result} />
<Route path="/" component={Landing} />
</Switch>
</BrowserRouter>
</StylesProvider>
</div>
);
};
Redirect is a component that must be rendered in order to have an effect, you're returning it from the hook but not doing anything with it.
You're looking for history.push('/result'). It serves the same purpose, but instead of rendering a component responsible for the redirect, you do it programmatically by updating the history.
See the docs on the useHistory.