Skip to content

Commit 0bf630b

Browse files
committed
refactored async state with react-query, implemented global app state
1 parent 3b5cb08 commit 0bf630b

14 files changed

+11028
-11413
lines changed

components/SearchBar.js

+59-63
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,69 @@
1-
import { useEffect, useState } from "react";
1+
import { useState } from "react";
22
import { Popover, Transition } from "@headlessui/react";
33
import { Search } from "react-feather";
4-
import Input from './Input';
4+
import Input from "./Input";
55
import { useRouter } from "next/router";
6+
import { useQuery } from "react-query";
7+
import { structurePolls } from "./Utils";
8+
import useVoting from "../hooks/useVoting";
69

710
function SearchBar() {
8-
const [polls, setPolls] = useState([])
9-
const [pollID, setPollID] = useState("")
10-
const router = useRouter();
11-
useEffect(() => {
12-
const polls = JSON.parse(localStorage.getItem("polls"))
13-
if (polls !== null) {
14-
setPolls(polls)
15-
}
16-
}, [])
11+
const voting = useVoting({});
12+
const [pollID, setPollID] = useState("");
13+
const router = useRouter();
14+
const { data: pollData } = useQuery("polls", async () => {
15+
const { contract } = await voting;
16+
const polls = await contract.getPolls();
17+
return structurePolls(polls);
18+
});
19+
const polls = pollData ?? [];
1720

18-
// useEffect(() => {
19-
// const listener = event => {
20-
// if (event.code === "Enter" || event.code === "NumpadEnter") {
21-
// console.log("Enter key was pressed. Run your function.");
22-
// event.preventDefault();
23-
// // callMyFunction();
24-
// }
25-
// };
26-
// document.addEventListener("keydown", listener);
27-
// return () => {
28-
// document.removeEventListener("keydown", listener);
29-
// };
30-
// }, []);
21+
const handleChange = (e) => {
22+
setPollID(e.target.value);
23+
};
3124

32-
const handleChange = e => {
33-
setPollID(e.target.value)
34-
}
35-
36-
const handleSubmit = e => {
37-
e.preventDefault()
38-
console.log(pollID)
39-
router.push(`/pollDetails/${pollID}`)
40-
}
41-
return (
42-
<Popover className="relative">
43-
{({ open }) => (
44-
<>
45-
<Popover.Button className="focus:outline-none pt-1">
46-
<Search className={`cursor-pointerz-50 ${open && "text-primary"}`} />
47-
</Popover.Button>
48-
<Transition
49-
enter="transition ease-out duration-200"
50-
enterFrom="opacity-0 translate-x-1"
51-
enterTo="opacity-100 translate-x-0"
52-
leave="transition ease-in duration-150"
53-
leaveFrom="opacity-100 translate-x-0"
54-
leaveTo="opacity-0 translate-x-1"
55-
>
56-
<Popover.Panel className="absolute z-10 lg:-left-72 lg:-ml-10 -ml-48 -top-3">
57-
<form onSubmit={handleSubmit}>
58-
<Input onChange={handleChange} list="polls" placeholder="Search for past and present polls" width="lg:w-80" />
59-
<datalist id="polls" width="lg:w-80">
60-
{polls.length > 0 && polls.map(poll => (
61-
<option value={poll.name} key={poll.id} />
62-
))}
63-
</datalist>
64-
</form>
65-
</Popover.Panel>
66-
</Transition>
67-
</>
68-
)}
69-
</Popover>
70-
);
25+
const handleSubmit = (e) => {
26+
e.preventDefault();
27+
router.push(`/pollDetails/${pollID}`);
28+
};
29+
return (
30+
<Popover className="relative">
31+
{({ open }) => (
32+
<>
33+
<Popover.Button className="focus:outline-none pt-1">
34+
<Search
35+
className={`cursor-pointerz-50 ${open && "text-primary"}`}
36+
/>
37+
</Popover.Button>
38+
<Transition
39+
enter="transition ease-out duration-200"
40+
enterFrom="opacity-0 translate-x-1"
41+
enterTo="opacity-100 translate-x-0"
42+
leave="transition ease-in duration-150"
43+
leaveFrom="opacity-100 translate-x-0"
44+
leaveTo="opacity-0 translate-x-1"
45+
>
46+
<Popover.Panel className="absolute z-10 lg:-left-72 lg:-ml-10 -ml-48 -top-3">
47+
<form onSubmit={handleSubmit}>
48+
<Input
49+
onChange={handleChange}
50+
list="polls"
51+
placeholder="Search for past and present polls"
52+
width="lg:w-80"
53+
/>
54+
<datalist id="polls" width="lg:w-80">
55+
{polls.length > 0 &&
56+
polls.map((poll) => (
57+
<option value={poll.name} key={poll.id} />
58+
))}
59+
</datalist>
60+
</form>
61+
</Popover.Panel>
62+
</Transition>
63+
</>
64+
)}
65+
</Popover>
66+
);
7167
}
7268

7369
export default SearchBar;

components/Utils.js

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export const structurePolls = (allPolls) => {
2222
}
2323
})
2424

25-
console.log(polls)
2625
return polls
2726
}
2827

context/AppDetails.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { createContext, useState } from "react";
2+
3+
//create a context, with createContext api
4+
export const appDetailsContext = createContext();
5+
const { Provider } = appDetailsContext;
6+
7+
const AppDetailsProvider = (props) => {
8+
// this state will be shared with all components
9+
const [appDetails, setAppDetails] = useState({
10+
network: "",
11+
address: "",
12+
});
13+
14+
return (
15+
<Provider value={[appDetails, setAppDetails]}>{props.children}</Provider>
16+
);
17+
};
18+
19+
export default AppDetailsProvider;

hooks/useRedirectLogin.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import { useRouter } from "next/router";
2-
import { useEffect, useState } from "react";
2+
import { useContext, useEffect, useState } from "react";
3+
import { appDetailsContext } from "../context/AppDetails";
34
import routeNames from "../routes";
45

56
export const useRedirectLogin = () => {
67
const [pageLoading, setPageLoading] = useState(true);
78
const router = useRouter();
9+
const [appDetails] = useContext(appDetailsContext);
810

911
useEffect(() => {
1012
const isAuthRoute = router.pathname === routeNames.login;
11-
const user = localStorage.getItem("dappUser")
13+
const user = localStorage.getItem("dappUser");
1214
const connectedWallet =
1315
typeof window.ethereum !== "undefined" &&
1416
!(window.ethereum.selectedAddress === null);
15-
if (!isAuthRoute && !connectedWallet && user !== null) {
17+
if (!isAuthRoute && appDetails["address"] === "") {
1618
router.replace(routeNames.login);
1719
} else {
1820
setPageLoading(false);
1921
}
20-
}, [router.pathname]);
22+
}, [router, appDetails]);
23+
2124
return { pageLoading };
2225
};

hooks/useVoting.js

+26-19
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,32 @@ import { ethers } from "ethers";
22
import Web3Modal from "web3modal";
33
import Voting from "../artifacts/contracts/Voting.sol/Voting.json";
44

5-
const useVoting = async () => {
6-
const web3Modal = new Web3Modal({
7-
network: "mumbai",
8-
});
9-
10-
const connection = await web3Modal.connect();
11-
12-
const provider = new ethers.providers.Web3Provider(connection);
13-
14-
const signer = provider.getSigner();
15-
16-
const contract = new ethers.Contract(
17-
"0xfFD1a7105Fae1774971654EE8DcccC30Bb4846Cf",
18-
Voting.abi,
19-
signer
20-
);
21-
const address = await signer.getAddress();
22-
23-
return { address, contract };
5+
const useVoting = async ({ getRequest = true }) => {
6+
if (getRequest) {
7+
const provider = new ethers.providers.JsonRpcProvider({
8+
url: "https://rpc-mumbai.maticvigil.com/",
9+
});
10+
const contract = new ethers.Contract(
11+
"0xfFD1a7105Fae1774971654EE8DcccC30Bb4846Cf",
12+
Voting.abi,
13+
provider
14+
);
15+
return { contract };
16+
} else {
17+
/* needs the user to sign the transaction, so will use Web3Provider and sign it */
18+
const web3Modal = new Web3Modal();
19+
const connection = await web3Modal.connect();
20+
const provider = new ethers.providers.Web3Provider(connection);
21+
const signer = provider.getSigner();
22+
const chainId = await provider.getNetwork();
23+
const address = await signer.getAddress();
24+
const contract = new ethers.Contract(
25+
"0xfFD1a7105Fae1774971654EE8DcccC30Bb4846Cf",
26+
Voting.abi,
27+
signer
28+
);
29+
return { address, contract };
30+
}
2431
};
2532

2633
export default useVoting;

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"react": "17.0.2",
2121
"react-dom": "17.0.2",
2222
"react-feather": "^2.0.9",
23+
"react-query": "^3.34.7",
2324
"swr": "^0.5.6",
2425
"web3modal": "^1.9.3"
2526
},

pages/_app.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { QueryClient, QueryClientProvider } from "react-query";
2+
import AppDetailsProvider from "../context/AppDetails";
13
import { useRedirectLogin } from "../hooks/useRedirectLogin";
24
import "../styles/globals.css";
35

@@ -7,10 +9,15 @@ const Wrapper = ({ children }) => {
79
};
810

911
function MyApp({ Component, pageProps }) {
12+
const queryClient = new QueryClient();
1013
return (
11-
<Wrapper>
12-
<Component {...pageProps} />
13-
</Wrapper>
14+
<QueryClientProvider client={queryClient}>
15+
<AppDetailsProvider>
16+
<Wrapper>
17+
<Component {...pageProps} />
18+
</Wrapper>
19+
</AppDetailsProvider>
20+
</QueryClientProvider>
1421
);
1522
}
1623

0 commit comments

Comments
 (0)