//tips
//smart contract
Next-authだけでなくnext.jsの記述も確認。
If you export an async function called getServerSideProps from a page, Next.js will pre-render this page on each request using the data returned by getServerSideProps.
Usesessionを使わない方法だとSessionProvider を_appで使えないなどの制約があるのか、{session}の書き方を変える必要があるのかを調べる。
console.log(JSON.stringify(session));であったことから、sessionそのものが引き継げていないことがわかっている。
Nextのドキュメントを見ていくと結局usesessionと getServerSidePropsを併用していることがわかった。この辺りは謎。
https://github.com/nextauthjs/next-auth-example/blob/main/pages/server.tsx
結局、下記の形で進めるのが今の所ベストとなりそう。
export default function Home() {//{ session }
const { data: session } = useSession()
バージョンアップでまた変わる可能性がある箇所として認識しておく。
The useSession() React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
useSession() returns an object containing two values: data and status:
data: This can be three values: Session / undefined / null.
-when the session hasn't been fetched yet, data will undefined
-in case it failed to retrieve the session, data will be null
-in case of success, data will be Session.
status: enum mapping to three possible session states: "loading" | "authenticated" | "unauthenticated"
また、プロテクトされているページのロードはuserのセッションが有効かどうかサーバ側リクエストを作り、SSTページを生成する。
every protected page load has to make a server-side request to check if the session is valid and then generate the requested page (SSR).
stringify() は、JavaScriptオブジェクトを取得し、JSON 文字列に変換するので、parseと間違えない。
JSON.parse() は、JSON 文字列を取得し、JavaScriptオブジェクトに変換。JSON.stringify() は、JavaScriptオブジェクトを取得し、JSON 文字列に変換。
const myObj = {
name: 'Skip',
age: 2,
favoriteFood: 'Steak'
};
const myObjStr = JSON.stringify(myObj);
console.log(myObjStr);
// "{"name":"Sammy","age":6,"favoriteFood":"Tofu"}"
クライアントサイドとサーバサイドのやりとりの認識が足りないためgetServerSidePropsの穴が見つけられないのかもしれないと、node.jsの仕組みの部分から確認。
プロキシ部分は関係ないように思えるので、pageのルーティングがそもそもhttpのgetなどによるルーティングをベースにされており、page下のファイル名がurlの/後に反映され、そこがアクセス先として利用されることは認識しておく。
ブラウザから/fooでサーバにアクセスされた場合、SSRなら完全なhtmlを返し、ブラウザ側で一部jsの紐付け処理(ハイドレーション)が行われるが、ここでは問題なさそう。有識者に聞く。
メインパートに構造を融合させる前に、他に調べた方が良さそうな要素を確認。
ユーザーがブラウザでイベント処理を行う場合の動作も確認。
<form onSubmit={handleOnTweetSubmit}>
<button>Tweet</button>
フォームの中にボタンを作り、ボタンが押されたら指定のイベントを実行させるように設定。
イベントの中身は別ページの内容を取得するのでasyncを使用している。e.preventDefault();はイベント発生に伴い、デフォルト機能であるページの再読み込みを行わせないようにe.preventDefault();を実行。
FormDataオブジェクトとは、サーバーにデータを送信する際に使用するオブジェクトで、ユーザーが入力するフォームデータや、任意のデータをサーバーに送信できる。内容はキー・バリューのペアとして利用。
HTMLの<form>要素からFormDataオブジェクトを作成することができる。
async function handleOnSearchSubmit(e) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const query = formData.get('query');
const results = await fetch('/api/twitter/search', {//ここでserch.jsに飛ばし
method: 'POST',
body: JSON.stringify({
query
})
}).then(res => res.json());
setStatuses(results.data);
}
ここでformData.getとし、キーqueryを指定することで、FormDataオブジェクト内のqueryのバリューを受け取ることができる。このキーはform内で下記のように指定されたもの。
<input type="search" name="query" />
バリューはインプット内容。formData.get()は引数にキー名を渡すと、値を返すもの。
ちなみにEvent.currentTarget と Event.targetの違いは、Event.currentTargetはイベント発生内容ではなく、イベントを発生させたボタンの登録内容を取得するもの。
Event.currentTarget:イベントハンドラを登録した要素
Event.target:イベントが発生した要素
ここではname="query" を取得したかったので、このようにしている。
参考:
https://javascript.keicode.com/newjs/how-to-use-formdata.php#1
https://qiita.com/_Keitaro_/items/6a3342735d3429175300
さらに、イベントで外部データの取得を行わせるため、search.jsに飛ばして、オブジェクトからjsonテキストに変換したインプット内容をpostでサーバへデータ送付。
const results = await fetch('/api/twitter/search', {//ここでserch.jsに飛ばし
method: 'POST',
body: JSON.stringify({
query
})
}).then(res => res.json());
ここでserch側のapi処理内容を確認。
req.bodyでpostされたインプット内容を取得。このreqの中にsession情報とtoken情報も含まれているよう。
export default async (req, res) => {//APIのルートの一つ/search
const body = JSON.parse(req.body);
const { query } = body;
const session = await getSession({ req });
const token = await getToken({
req,
secret: process.env.NEXTAUTH_SECRET
});
const client = new Twitter({
subdomain: 'api',
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token_key: token.twitter.accessToken,
access_token_secret: token.twitter.refreshToken
});
try {
const results = await client.get('search/tweets', {
q: query
});
return res.status(200).json({
status: 'Ok',
data: results.statuses
});
} catch(e) {
return res.status(400).json({
status: e.message
});
}
}
Tokenの方はjetコンテンツからの取得となるそう。同時にNEXTAUTH_URL environment variable の設定も必要とのこと。
If you are using JSON Web Tokens you can use the getToken() helper to access the contents of the JWT without having to handle JWT decryption / verification yourself. This method can only be used server side.
You can use the getToken() helper function in any application as long as you set the NEXTAUTH_URL environment variable and the application is able to read the JWT cookie (e.g. is on the same domain).
この際に secret: process.env.NEXTAUTH_SECRETを一緒に渡す。
Pass getToken the same value for secret as specified in pages/api/auth/[...nextauth].js.
https://next-auth.js.org/configuration/options#jwt
twitterの認証はtwitter-liteの機能を用い、await client.get('search/tweets’,でインプット内容を引数にtwitterでの検索結果を取得する。
https://www.npmjs.com/package/twitter-lite
これを使って、別途searchではなくtimelineを表示する機能も追加する。
https://github.com/draftbit/twitter-lite