20210603のReactに関する記事は4件です。

Ionic Reactでページ遷移をios風にスライドアニメーション付にする方法

サンプル ionic serveで起動して挙動確認してみてください。 サンプルソース 大事な部分 ①まず、IonApp, IonReactRouter, IonRouterOutletタグがしっかり使われているか確認しましょう。 ②setupConfig({mode: 'ios'})を指定しましょう。(デフォだと違うアニメーションが適用されてるので、iosを指定する必要がある) const App: React.FC = () => { setupConfig({mode: 'ios'}) return ( <IonApp> <IonReactRouter> <IonRouterOutlet> <Route path="/tab1" component={Tab1} exact={true} /> <Route path="/tab2" component={Tab2} exact={true} /> <Route path="/tab2/details" component={Details} /> <Route path="/tab3" component={Tab3} /> <Route path="/" render={() => <Redirect to="/tab1" />} exact={true} /> </IonRouterOutlet> </IonReactRouter> </IonApp> ); } ③IonPageでしっかりラップする。 ④routerLinkで遷移先、routerDirectionで遷移する方向を指定しましょう "forward" | "back" | "none" "root" const Tab1: React.FC = () => { return ( <IonPage> <IonHeader> <IonToolbar> <IonTitle>Tab 1</IonTitle> </IonToolbar> </IonHeader> <IonContent> <IonHeader collapse="condense"> <IonToolbar> <IonTitle size="large">Tab 1</IonTitle> </IonToolbar> </IonHeader> <ExploreContainer name="Tab 1 page" /> <IonList> <IonItem routerLink="/tab3" routerDirection="forward"> <IonLabel>tab 3</IonLabel> </IonItem> <IonItem routerLink="/tab2" routerDirection="forward"> <IonLabel>tab 2</IonLabel> </IonItem> </IonList> </IonContent> </IonPage> ); }; まとめ 何をどうすれば、ページ遷移時のアニメーションが追加されるのかがわかりにくくめちゃくちゃハマった。 よく公式読んだらIonReactRouter, IonRouterOutlet, IonPage, Navigationを全部使わないとダメなんだろうな、、ということがわかった。 https://ionicframework.com/jp/docs/react/navigation#ionrouteroutlet
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

react-splineを使って、自分で作った3Dモデルを動かしてみた。

ふと検索したら「react-spline」というライブラリがある事を知ったので、触ってみます。 また、これが qiita初投稿です。書き方が微妙かもしれませんがご了承下さい。 まずは作ったものを紹介 localで動いているのが分かると思います。 もともと3Dモデルが用意されていたのですが、 ちょっとだけ手を加えて右翼の支柱を2本取っておきました。 実装手順 2ステップで説明していきます。 「2」はモデル作成の方法と、作成したモデルを取り込む手順です。 私は3Dモデル作成は詳しく無いので、動画のとおり 棒を2本無くしただけです。 自作モデルは作らなくていいから、とりあえず動かしたい人 自作モデルを作成して、reactに組み込みたい人 1.自作モデルは作らなくていいから、とりあえず動かしたい人 早速説明していきます。でライブラリをクローンしてきます。 クローンしたらexampleフォルダに入って、npm iです。 git clone https://github.com/utkarshdubey/react-spline.git cd react-spline cd example npm install (または、 yarn install) あとは、npm install で完了です。 npm start (または、 yarn start) 動かすだけならこれで完了 うまくいけば 「localhost:3000」で以下の画面が表示されて、ぬるぬる動かせます。 ソース的にはこんな感じです。まんまreactですね。 「import { SPLINE_EXPORTED_SCENE } from './scene'」の部分でjson形式のモデルを読み込んでいるんですが、次の項目でその部分を作成していきます。 import React from 'react' import { SPLINE_EXPORTED_SCENE } from './scene' import { Spline } from 'react-spline' const App = () => { return ( <div> <div style={{ backgroundSize: 'cover', display: 'flex', justifyContent: 'center', alignItems: 'center' }} > <h1 style={{ position: 'absolute', zIndex: 1, color: '#fff' }}> If you see this, react-spline works. </h1> <Spline scene={SPLINE_EXPORTED_SCENE} /> </div> </div> ) } export default App 2.自作モデルを作成して、reactに組み込みたい人 モデルの作成 ここからは「自作モデルを作成して、reactに組み込みたい人」編に突入です。 公式HPから「Spline」をダウンロードします。「download now」のクリックだけで難しくなかったです。 ダウンロードしたらこんな感じの画面になります。 赤部分をクリックして、少しだけモデルに修正を加えていきます。 私は、3Dモデルをいじるスキルは低いので、とりあえず大事そうな支柱を2本抜いておきました。 作成した3Dモデルをexport これが簡単でびっくりしました。 以下はexportからブラウザで表示までの流れです。 作成された3Dモデル ※多分このモデルが見れるのは有効期限があると思います。 2021/6/3 作成したモデルをjson形式に変更する 「作成された3Dモデル」の最後に「scene.json」を付与します。 ・json出力用URL https://my.spline.design/airplane-d369decdf14902501f8c46fa4fa24536/scene.json サンプルのモデルを自作モデルと差し替える ダウンロードした「scene.json」を、元々ある「scense.js」と置き換えます。 この際に注意するのは、 「scene.json」と「scense.js」は拡張しが違う ダウンロードしてきた方は先頭に「export const SPLINE_EXPORTED_SCENE = 」が無いので付ける ダウンロードしてきた方は最後にセミコロン(;)が無いので付ける。 この状態でうまくいけば、自作の3Dモデルがローカルで表示されているはずです! 分からなかったこと 実際に動いている画面をみると一部モノクロになっており、色が反映されていない箇所があります。 その部分については、原因がわかりませんでした。 違うモデルだったら、大丈夫だったのかな・・ 最後に 最近ブログを作成しました。reactにも触れているので良かったら見てみてください。 ・いはかよ https://www.ihakayo.com/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NextjsでGMOペイメントゲートウェイのカードを登録する処理(プロトコルタイプ)

対象読者 NextやReactでcdnを使いたい方 GMOペイメントゲートウェイをNextやReactで使いたい方 1の人はまとめまで飛んで下さい バックグラウンド 業務で新サービスを作っています。 バックエンドはLaravel、フロントエンドはNextjsを使用しています。 その新サービスでは決済はクレジットカードを利用しています。 決済に関しては個人的にはstripeが良かったのですが、費用とかを鑑みた末... 選ばれたのはGMOでした また仕様によりプロトコルタイプを選択しました。 stripe等のサービスと違いSDKもなくライブラリも充実しているわけでは無いのでなかなかに実装に工夫が必要でした。 値段とサービスどちらを取るかという論点は人によって価値観が違うので一概にどちらが優れているという比較はできませんが、これだけは言わせてください。 ドキュメントに関して一言だけ文句を言わせてください。このドキュメントの多さと分かりにくさ、「あえて言おう、カスであると」 嘘です。GMOさんGMOの皆さんごめんなさい このセリフ一度でいいから言ってみたかっただけなんです GMOの良さはstripeやpaypalより手数料が安いところです。 あと電話サポートの方の対応は丁寧かつ、技術の知識もあるためか正確な返答が得られた点がとても良かったです。 ドキュメントで躓いたら片っ端から電話しましょう! ただ公平な目で判断した際に少し手間であるのは紛れもない事実です。これからのユーザーやGMOさんのためにもなると思ったのでこの記事を書くことにしました。強いられてるんだQiitaを書くことを 前提条件 カードから毎月反響した分だけ引き下ろすためにはカードの持ち主をGMOに登録しておくことと、カード自体を登録する必要があります。 GMOのAPIからの返り値をarrayにする汎用関数 不満点その2。返り値が不親切であること そのため使いやすく整形して返す関数を定義しました。 まずgmoのAPIから帰ってくる生のbodyがこちらです。 "CardSeq=0&DefaultFlag=1&CardName=&CardNo=*************111&Expire=2405&HolderName=&DeleteFlag=0" ええ、、、&つなぎの文字列、、、 「あえて言おう、(自重) このままだと使いにくいんで配列に変換する汎用関数を作ります。 curlやguzzleで取ってきた値を$rawReturnと仮定します public static function gmoFormatter(string $url, array $params): array { $rawReturn = self::postCurl($url, $params); // 実際にpostする汎用関数(長くなるので中身は省略) curlでもguzzleでも好きなものを使ってください $status = $rawRet['status']; $dataList = explode('&', $rawReturn['data']); // & 分解 foreach($dataList as $d) { $dkv = explode('=', $data); // = 分解: 左辺がkey, 右辺がvalueになっている $ret[$dkv[0]] = $dkv[1]; $dkv[0] === 'ErrCode' && $status === 200 && $status = 400; // 通信が成功しつつエラーコードがあればstatusを400にしちゃいます } $ret = ['status' => $status, 'data' => $ret]; // エラーコードがあったときにはstatusを書き換えているので判定がしやすくなっています。 return $ret; } 以下が整形した結果の配列です。どうでしょう? 圧倒的じゃないか、我が軍は { "stauts":200, "data":[ { "CardSeq":"0", "DefaultFlag":"1", "CardName":"", "CardNo":"*************111", "Expire":"2405", "HolderName":"", "DeleteFlag":"0" } ] } あらかじめ会員登録をしておいてメンバーIDを作っておく 毎月決済するための加盟店のカードを登録するためには加盟店をGMOのショップの会員に登録した上で、その会員のカードがどれかわからなければなりません。 そこで、今回はサービスの会員登録時に発行される一意のユーザーIDを利用して、memberIDを作成します。 そしてそのmemberIDと加盟店の名前を元にGMOのショップの会員としても同時に登録する処理を行なっています。 一言で言うと、ユーザーのinsertと並列してGMO側にも必要な情報を投げて会員登録している形になります。 use App\Domains\GmoCurlDomain; class GmoDomain { private function __constructor() { // gmo env系 $this->apiUrl = config('custom.gmoApiUrl'); $this->siteId = config('custom.gmoSiteId'); $this->sitePw = config('custom.gmoSitePw'); $this->shopId = config('custom.gmoShopId'); $this->shopPw = config('custom.gmoShopPw'); } /** * 会員登録する * @param String $memberName * @param String $memberId * @return Array $exe */ public function saveMember(string $memberName, string $memberId): array { $url = $this->apiUrl . '/' . 'payment/' . 'SaveMember.idPass'; $params = [ 'SiteID' => $this->siteId, 'SitePass' => $this->sitePw, 'MemberID' => $memberId, 'MemberName' => mb_convert_encoding($memberName, 'SJIS', 'UTF-8'), // 文字化け用に mb_convert_encoding ]; $exe = GmoCurlDomain::gmoFormatter($url, $params); return $exe; } } プロトコルタイプってなに? トークン決済ってなに? カード登録や決済の際のお話です。 加盟店のサーバーサイド等を経由して入力されたカード番号を直接GMOのカード登録や決済が行われるとカード番号の流出等のリスクが上がってしまうので、GMOではこのトークン決済というものを利用しています。 プロトコルタイプでカード登録をする方法2選 入力されたカード番号から決済やカード登録に必要なトークンを取得するために以下の2つの方法があります。 それぞれエンドポイントは違います。 そのままAPIに投げる (sslのみ有効) cdnを利用してAPIに投げる (sslじゃなくてもOK) cdnを利用するとPOSTする前に暗号化してPOSTしてくれます。これでsslの代わりを担って通信を安全にしてくれています。 今回私は、ローカルでもテストとして使用したかったので2を選択しました。 Nextjs(React)でクレカを登録する 前提条件 GMOから受け取ったtokenを使ってクレカを登録する際には、以下の様な処理を行うAPIにポストしています。 もらってきたtokenと顧客固有のid(saveMemberのときにポストしたものと同じもの)やサイトID等を投げます。 カードの番号はもちろん、セキュリティコード、有効期限等が含まれていないのがちゃんとわかります。 public function saveNewCard( string $memberId, string $token ): array { $url = $this->apiUrl . '/' . 'payment/' . 'SaveCard.idPass'; $params = [ 'SiteID' => $this->siteId, 'SitePass' => $this->sitePw, 'MemberID' => $memberId, 'Token' => $token, 'DefaultFlag' => 1, ]; $exe = GmoCurlDomain::gmoFormatter($url, $params); return $exe; } Nextjs(React)でcdn内のclassをインスタンス化 Nextjsでcdnのクラスをインスタンス化して使う?できらぁ! cdnで定義されたクラスをインスタンス化する際に、いかにそのクラスをNext(React)上に記述しないかが重要なポイントです。 以下のプロセスはそれを念頭に置いた上で行いました。 Multipayment がそのアンタッチャブルなクラスに該当します。 失敗例1 (devだと動くけどcompileはできない例) dangerouslySetInnerHTMLを使用しています。 getCreateCardTokenはdangerouslySetInnerHTMLで定義したつもりですが、それはブラウザ上で定義されているだけで、next(react)内では定義してないのもちろんコンパイルはできません。でnpm run devでは動きますが、、、 const Credit: NextPage = () => { const [mess, setMess] = useState<string[]>([]); const startCreateCard = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); setMess(['送信中']); const ret = await getCreateCardToken(e); if (ret && ret['resultCode'] === '000') { // カード情報のトークン化に成功すればresultCode 000が返ってきます const res: Response = await fetchCreateCredit(newToken); // 返ってきたtokenをバックエンドにPOST // バックエンドでは受け取ったトークンやユーザー情報を利用してGMOのカード作成エンドポイントにポストする switch (res.status) { case 200: setMess(null); router.push(`<next page>`) break; default: setMess([`エラーが発生しました。`]); } } else { setMess([`エラーが発生しました。`]); } }; return ( <div> <Head> <script defer src={`${GMO_TOKEN_URL}`}></script>{/* cdnのurlです */} <script defer dangerouslySetInnerHTML={{ __html: ` // 定義されたままになるので再定義可能なvarを使う!! // 即読み込みできないのでタイムアウト setTimeout(() => { Multipayment.init('<shopID>'); }, 1000); // componentの移動の際にも定義されたままになるので再定義可能なvarを使う!! var getCreateCardToken = (e) => { return new Promise(function (resolve, reject) { Multipayment.getToken( { cardno: e.target.card.value, expire: e.target.expire.value, securitycode: e.target.securitycode.value, }, resolve ); }); } `, }} /> </Head> <form onSubmit={startCreateCard}> <label>カード番号</label> <input type="text" name="card" required maxLength={16} minLength={16} /> 以下省略 </form> </div> ) } export default Credit; 失敗例2 (compileできるけど動かない例) では、適当にgetCreateCardTokenを宣言だけしてみたらどうだろう? 上のコードに以下を追加してみます。 useEffect(() => { var getCreateCardToken: Function; }, []); ページがマウントされた後にgetCreateCardTokenを宣言、dangerouslySetInnerHTMLでgetCreateCardTokenを上書きする作戦です。 "getCreateCardToken" is not a function これならとりあえずはコンパイルできる状態にはなりました。 しかし、今度はブラウザ上で動かない。 dangerouslySetInnerHTMLで上書きするとgetCreateCardTokenはundefinedとなってしまっていました。 この後も色々と試行錯誤したが、長くなるので割愛します。 正解 コンパイルできて、ちゃんと動く正解の形です。 文字列を関数に変換できればいいのではないか?と思い、このような実装をしました。 予想通り完璧に動きました。 const Credit: NextPage = () => { const [mess, setMess] = useState<string[]>([]); const strFunction = ` Multipayment.init('${GMO_KEY}'); return new Promise(function (resolve, reject) { Multipayment.getToken( { cardno: e.target.card.value, expire: e.target.expire.value, securitycode: e.target.securitycode.value, }, resolve ); }); `; let getCreateCardToken = new Function('e', strFunction); useEffect(() => { getCreateCardToken = new Function('e', setFunction); }, []); const startCreateCard = async (e: React.FormEventHandler<HTMLFormElement>) => { e.preventDefault(); setMess(['送信中']); const ret = await getCreateCardToken(e); if (ret && ret['resultCode'] === '000') { // カード情報のトークン化に成功すればresultCode 000が返ってきます const res: Response = await fetchCreateCredit(newToken); // 返ってきたtokenをバックエンドにPOST // バックエンドでは受け取ったトークンやユーザー情報を利用してGMOのカード作成エンドポイントにポストする switch (res.status) { case 200: setMess(null); router.push(`<next page>`) break; default: setMess([`エラーが発生しました。`]); } } else { setMess([`エラーが発生しました。`]); } }; return ( <div> <Head> <script defer src={`${GMO_TOKEN_URL}`}></script> </Head> <form onSubmit={startCreateCard}> <label>カード番号</label> <input type="text" name="card" required maxLength={16} minLength={16} /> 以下省略 </form> </div> ) } export default Credit; ミソはこの部分です。 const strFunction = ` Multipayment.init('${GMO_KEY}'); return new Promise(function (resolve, reject) { Multipayment.getToken( { cardno: e.target.card.value, expire: e.target.expire.value, securitycode: e.target.securitycode.value, }, resolve ); }); `; let getCreateCardToken = new Function('e', strFunction); // cdnがロードされていないので ここは意味合い的には宣言だけ useEffect(() => { getCreateCardToken = new Function('e', strFunction); // 上書きする ここで定義される。 cdnがロードされた後に実行される }, []); useStateでなく、letを使ったのは一回だけしか変更がないためletでいいかな〜って思ったからです。 let getCreateCardToken = new Function('e', strFunction) では以下のような処理が行われています。 let getCreateCardToken = (e) => { // strFunctionの中身 Multipayment.init('${GMO_KEY}'); return new Promise(function (resolve, reject) { Multipayment.getToken( { cardno: e.target.card.value, expire: e.target.expire.value, securitycode: e.target.securitycode.value, }, resolve ); }); } まとめ nextやreactでcdn内のクラスをインスタンス化して使いたい場合、以下のようにやると良いです。 import Head from 'next/head'; const Sample: NextPage = () => { const strFunction = ` <SomeClass>.init(); 何らかの処理 `; let cdnFunction = new Function('arg', strFunction); useEffect(() => { cdnFunction = new Function('arg', strFunction); }, []); return ( <div> <Head> <script src={`${CDN_SOURCE}`}></script> </Head> </div> ) } export default Sample; GMOペイメントゲートウェイについて、手数料が安く電話サポートが充実している点はとても素晴らしいと思います。 少し高くても手間をかけたくなかったらstripe、手間をかけてでも手数料を節約したいならGMOペイメントゲートウェイを選ぶといいんではないでしょうか。 最後に一言 すまんが、みんなのLGTMをくれ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaSctipt,TypeScript】論理演算子の基本と応用

基本 どちらの演算子も両方がTrueだったらTrue、FalseだったらFalseになる JavaScriptの仕様上判定は左から右へ行われる。 ||演算子 main.js console.log( true || true ) //true console.log( true || false ) //true console.log( false || true ) //true console.log( false || false ) //false 数学的な意味では「または」 記号であらわすと∪ a || b であればaまたはbのどちらかを満たす範囲 プログラミングであればどちらかがTrueであればTrueになる &&演算子 main.js console.log( true && true ) //true console.log( true && false ) //false console.log( false && true ) //false console.log( true && false ) //false 数学的な意味では「かつ」 記号であらわすと∩ a && b であればaまたはbの両方を満たす範囲 プログラミングであれば両方TrueでないとTrueにならない。 JavaScriptでの演算子の法則 ||演算子 ||の場合、左式がfalseもしくはfalseとみなすことができる(falsy)値の場合右式を返す これら全て出力は "右式を返すよ" になります。 main.js console.log( false || "右式を返すよ") console.log( 0 || "右式を返すよ") console.log( null || "右式を返すよ") console.log( undefined || "右式を返すよ") console.log( NaN || "右式を返すよ") console.log( "" || "右式を返すよ") &&演算子 &&の場合、左式がtrueもしくはtrueとみなすことができる(truthy)値の場合右式を返す これら全て出力は "右式を返すよ" になります。 main.js console.log( true && "右式を返すよ") console.log( 1 && "右式を返すよ") console.log( "左式だよ" && "右式を返すよ") これらの法則はほかのプログラミング言語でも使用できたりもします。 JavaScriptでの応用 Reactでの応用 ||の左式がtrueの場合右式を返却する仕組みを利用してこのような書き方が出来ます。 App.jsx import { useState, useEffect } from 'react'; export const App = () => { const [admin , setAdmin] = useState('false') return( <div> {admin && <AdminPage />} <div> ) } ①Admin(管理者)かどうか判定するStateを作成 ②管理者であればAdminPage(管理者画面)を出力する。 ※本来であれば管理者かどうかとかはhook化して汎用的にするのがベスト まとめ ||演算子 左式がfalseとみなすことができる値の場合、右式に設定されている値を返却 左式がtrueとみなせる場合はそのまま左式を返却 &&演算子 左式がtrueとみなすことができる値の場合、右式に設定されている値を返却 左式がfalseとみなせる場合はそのまま左式を返却 特にフロントエンド開発で上手いこと使いこなせればコードの質が上がりますが、 使いすぎて可読性を落とさないように注意しましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む