Github API Calls with personal access token Usage with Fetch with node JS and React JS - fetch

Today, I was playing around with GitHub API and I ran into the 60 calls per hour roadblock as described here - https://developer.github.com/v3/rate_limit/
For command line testing the solution is to use PAT - https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token
I am new learner but the GitHub doc was a little confusing so I had run around a lot. Github recommends the following CURL usage
curl -u GitHubUserName:personalaccesstoken https://api.github.com/users/GitHubUserName
but, then, using it in a fetch request is a challenge for there are a number of depreciation in the pipeline on how to use things.
So, the question, how best to get this working in a simple fetch call in node JS and React JS?

Eventually, I ended up with the following code block that gets it working.
import React, { useState, useEffect } from "react";
function GitHubUser({ login }) {
const [data, setData] = useState();
const [error, setError] = useState();
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!login) return;
setLoading(true);
fetch(`https://api.github.com/users/GitHubUserName`,{
method: "GET",
headers: {
Authorization: `token personalaccesstoken `
}
})
.then(data => data.json())
.then(setData)
.then(() => setLoading(false))
.catch(setError);
}, [login]);
if (loading) return <h1>loading...</h1>;
if (error)
return <pre>{JSON.stringify(error, null, 2)}</pre>;
if (!data) return null;
return (
<div className="githubUser">
<img
src={data.avatar_url}
alt={data.login}
style={{ width: 200 }}
/>
<div>
<h1>{data.login}</h1>
{data.name && <p>{data.name}</p>}
{data.location && <p>{data.location}</p>}
</div>
</div>
);
}
export default function App() {
return <GitHubUser login="GitHubUserName" />;
}
The main confusion was that in some parts of GitHub documentation it keeps saying we should use username, and basic and what not. Perhaps it was only confusion for me, but this solves it.

Related

How to use useState in root layout/page in app directory of nextjs 13

In Nextjs 13 - experimental app directory, if I wanted to use useState on the root layout/page I must add ‘use client’ to the code, which effectively prevents all nested components from being server components.. how can I work around this so that I can use useState and still have server components. Thanks to any responders.
I don't know if this answers to your question (it's better to add some example code to help users understand your problem)
If you create a Server Component, and in that component you add your Client Component, it works fine. For example
ClientComponent.tsx
"use client";
import {useState} from 'react';
export default function ClientComponent() {
const [count, setCount] = useState(0);
return (
<>
<h1>Client Component</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
)
}
ServerComponent.tsx
async function getData(){
const res = await fetch('http://localhost:3000/api/hello');
return await res.json();
}
export default async function ServerComponent() {
const data = await getData()
return (
<>
<h1>Server Component</h1>
<p>{data.name}</p>
</>
)
}
Api hello.ts
export default async function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
Your page
import ClientComponent from "./ClientComponent";
import ServerComponent from "./ServerComponent";
export default function Page() {
return(<>
<ClientComponent/>
<ServerComponent/>
</>
)
}
In this example ServerComponent is rendered on the server, but ClientComponent on the client so it maintain interactivity
Hope this will help

Nextjs 13 how to implement dynamic title

I'm having trouble with implementing dynamic title with Next.js 13.
The Documents said, (https://beta.nextjs.org/docs/routing/pages-and-layouts#modifying-head)
Warning: Currently, the <Head> export does not re-render on client-side transition using next/link, only on initial render and reloads. To work around this for <title>, you can use a client component with useEffect that updates document.title. We plan to fix this in a future release.
And then I tried with useEffect to implement dynamic title,
'use client';
import { useEffect } from "react";;
import Head from 'next/head';
interface Props {
params: {slug : string},
searchParams: {id:string}
};
const getPost = async (id: string) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
const posts = await res.json();
return posts;
};
const Page = ({params, searchParams}: Props) => {
useEffect(() => {
const setDocumentTitle = async () => {
const post = await getPost(params.slug);
document.title = post.title;
}
setDocumentTitle();
}, [params.slug]);
return (<>
<Head>
<title>Blog Post</title>
</Head>
<div>
<h1>Blog Post</h1>
<p>Slug: {params.slug}</p>
<p>Id: {searchParams.id}</p>
</div>
</>);
};
export default Page;
but it is not working. still title is not changed. Is there any way?
You can reproduce it here.codesandbox
The first few times seem to be working well, but the document title does not change if you continue to go back and click Go to Post1 (next/link).

Use tw elements in a NextJS project

I'm trying to use tw-elements in a nodejs project. If I follow their documentation and just import tw-elements in my _app, I get this error:
ReferenceError: document is not defined
I found a stackoverflow response that said to put this at the start of the index.min.js file of tw-elements:
if (typeof window == "undefined")return;
I did and the error disappeared, but the library still won't work. Any ideas?
First, add Tailwind Elements using these NPM steps here.
Here is how to get it to work with Nextjs:
First step is to add this code to your _app.js file:
useEffect(() => {
const use = async () => {
(await import('tw-elements')).default;
};
use();
}, []);
Like this for example:
export default function App({ Component, pageProps }) {
useEffect(() => {
const use = async () => {
(await import('tw-elements')).default;
};
use();
}, []);
return (
Make sure you add import { useEffect } from "react"; to the top of _app.js.
It’s also important that you’re not importing Tailwind Elements anywhere else expect for the _app.js file.
Tailwind Elements should now be working!
I was facing the same issue. I followed Tyrell Curry's answer but It encountered type not found error because I was using typescript.
Unfortunately the type definitions were missing for tailwind-elements library.
I made a little change it the function so that type check have to be avoided by using as any.
useEffect(() => {
const use = async () => {
(await import("tw-elements" as any)).default;
};
use();
}, []);

Not getting API response data in props using getStaticProps in next js

I am new to nextjs. I want to prerender a page on server and want to delay rendering till API call is resolved. to achieve this i am using getStaticProps as mentioned in nextjs official docs.
here is the position of the file in my code structure:-
i am exporting my getStaticProps from index.js
here is the code snippet :-
export const getStaticProps = async () => {
const res = await axios.get(`http://blogexample.com/blog/posts`);
const blogList = await res.data
return {
props: {
blogList
}
}
}
const Blog = (props) => {
const { blogList } = props;
useEffect(() => {
console.log('list',blogList)
},[blogList])
return(
....
);
}
export default Blog;
problem is that, in browser console....my console.log('list',blogList) statement prints undefined
what i am doing wrong
getStaticProps is executed during build time. Use getServerSideProps
instead.

Use async react-select with redux-saga

I try to implement a async react-select (Select.Async). The problem is, we want to do the fetch in redux-saga. So if a user types something, the fetch-action should be triggered. Saga then fetches the record and saved them to the store. This works so far.
Unfortunately loadOptions has to return a promise or the callback should be called. Since the newly retrieved options get propagated with a changing property, I see no way to use Select.Async together with saga to do the async fetch call. Any suggestions?
<Select.Async
multi={false}
value={this.props.value}
onChange={this.onChange}
loadOptions={(searchTerm) => this.props.options.load(searchTerm)}
/>
I had a hack where i assigned the callback to a class variable and resolve it on componentWillReceiveProps. That way ugly and did not work properly so i look for a better solution.
Thanks
redux-saga is for handling side effects like asynchronously receiving options for react-select. That's why you should leave the async stuff to redux-saga. I have never used react-select but by just looking at the documentation I would solve it this way:
Your component gets very simple. Just get value and options from your redux store. optionsRequested is an action creator for the OPTIONS_REQUESTED action:
const ConnectedSelect = ({ value, options, optionsRequested }) => (
<Select
value={value}
options={options}
onInputChange={optionsRequested}
/>
)
export default connect(store => ({
value: selectors.getValue(store),
options: selectors.getOptions(store),
}), {
optionsRequested: actions.optionsRequested,
})(ConnectedSelect)
A saga definition watches for OPTIONS_REQUESTED action that is trigged by onInputChange, loads the data with given searchTerm from server and dispatches OPTIONS_RECEIVED action to update redux store.
function* watchLoadOptions(searchTerm) {
const options = yield call(api.getOptions, searchTerm)
yield put(optionsReceived(options))
}
In other words: Make your Component as pure as possible and handle all side-effect/async calls in redux-saga
I hope this answer was useful for you.
The main idea is that you are capable to dispatch redux actions using application context from
import React from 'react';
import { connect } from 'react-redux';
import Select from '#components/Control/Form/Skin/Default/Select';
import { reduxGetter, reduxSetter, required as req } from '#helpers/form';
import { companyGetTrucksInit } from "#reduxActions/company";
import AppContext from '#app/AppContext';
const FIELD_NAME = 'truck';
export const getReduxValue = reduxGetter(FIELD_NAME);
export const setReduxValue = reduxSetter(FIELD_NAME);
const SelectCompanyTruck = (props) => {
const {
required,
validate=[]
} = props;
const vRules = [...validate];
if (required)
vRules.push(req);
return (
<AppContext.Consumer>
{({ dispatchAction }) => (
<Select
loadOptions={(inputValue, callback) => {
function handleResponse(response) {
const { data: { items } } = response;
const options = items.map(i => ({ label: i.name, value: i.id }));
callback(options);
}
dispatchAction(companyGetTrucksInit, { resolve: handleResponse, inputValue });
}}
name={FIELD_NAME}
{...props}
/>
)}
</AppContext.Consumer>
);
}
export default SelectCompanyTruck;

Resources