KAEDE Hack blog

JavaScript 中心に ライブラリなどの使い方を解説する技術ブログ。

Make-2ch-log

まずAppの中身をCLEAR

Bootstrap4をnpmで食わせる

npm i bootstrap

4.4.1が入った

npm i react-bootstrap

これも必要?1.01が入った

import 'bootstrap/dist/css/bootstrap.min.css';

これをimportして

import Button from 'react-bootstrap/Button';

btnで試してみる

  <Button variant="primary">Primary</Button>{' '}

Appのrenderにこれを書いたら読み込まれた!

[f:id:kei_s_lifehack:20200507051109p:plain]

[https://react-bootstrap.github.io/components/table/:embed:cite]

Reactだとかなりsimpleにbootstrapがかける

[f:id:kei_s_lifehack:20200507051254p:plain]

しかし2chのUIはこれ

[f:id:kei_s_lifehack:20200507052547p:plain]

tableのUIはこれ

[f:id:kei_s_lifehack:20200507052610p:plain]

次の行にcontentsかけないし,columnの幅も調整できん

grid三つ書くしかないか?

[f:id:kei_s_lifehack:20200507120627p:plain]

思ったよりいい感じになった

import React from 'react';
import Writing from './components/Writing';

function App() {
  return (
    <div>
      <Writing/ >
    </div>
  );
}

export default App;

App側を簡単にかけるの便利だ

Database

まずはconsoleでfirestoreで

Add Firebase to Your AppのところでNick Name

firestoreを書いていく まずは src/Config/config.jsに

Add Firebase to Your AppのところでNick Name

npm i firebase

import firebase from 'firebase/app';

const firebaseConfig = ... {
apiKey = xxxxxx;

const firebaseApp = firebase.initializeApp(config);
export const firestore = firebaseApp.firestore();
.....
}

これをfirestoreとしてWritingでimport

refにuseStateを使ってみよう!!

dev.to

constructor直下に

this.ref = firebase.firestore().collection('notes');

で書いていたのを

const [ref, setRef] = useState[ firebase.firestore().collection('writings')];

に置き換える

useEffectがわからんが,どうやらcomponentWillMountに近いものらしい

[https://qiita.com/keiya01/items/fc5c725fed1ec53c24c5#%E8%89%AF%E3%81%84%E4%BE%8B-3:embed:cite]

この記事によると

useEffect(                                   
    () => {                                  
        const time = setInterval(() => {     
            dispatch({ type: "ADD_COUNT" }); 
        }, state.tick);                      
                                             
        return () => clearInterval(time);    
    },                                       
    [ state.tick ]                           
);                                           

これでstate.tickが変化するたびに「副作用」として処理を追加できるらしい

reactjs.org

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

公式にはこのような記載がある.htmlのtitleも変更できるようだ

このコードでは[]に最後に入れてないから,何も入れてなければbrowser APIで何か 変数が更新されたのを検知してuseEffectをうごかすのだろうか.

TypeError: storeRef.onShapshot is not a function (anonymous function) src/components/Writing.jsx:37 34 | 35 | useEffect( 36 | () => {

37 | let unsub = storeRef.onShapshot( | ^ 38 | update 39 | ); 40 | }

storeRef.onShapShotがuseEffectではとれない....

storeRefの中身は確認してある.hooksでclassのやり方はできないようだ

blog.logrocket.com

全部はわからんがここのコードを使ってみる

export const createWrintings = (writings) => {
  return storeRef.add({
    created: firebase.firestore.FieldValue.serverTimestamp(),
    content: writings,
  });
};

create, addは簡単に作れた.stateは使わないようだ

SHOWができないから

qiita.com

これを使ってみる

github.com

react-firebase-hooks というツールを使う

npm install --save react-firebase-hooks

Writing.jsxにはいつもの

import firebase from 'firebase/app';
import { firestore } from '../Config/config';

の他に

import {useCollectionData} from 'react-firebase-hooks/firestore';

をしてさっきnpm i したのを読んで

  const [values, loading, error,] = useCollectionData(
    ref, {idField: 'id'});

で設定する

  if(loading) {
    return <div>Loading...</div>
  }
  if(error) {
    return <div>{`Error: ${error.message}`}</div>
  }

loading, errorではこれらを返し

  return (
    <ul>
      {values.map(value => (
        <li key = {value.id}>{value.content}</li>
      ))}
    </ul>
  )

return ではvalueをmapするだけ doc...とか一切必要がない

これだけでfirestore collectionからDOMに書き込めた

f:id:kei_s_lifehack:20200514012525p:plain

valuesをcllすると

(2) [{…}, {…}]
0: {created_at: t, content: "俺みたいな中3でグロ見てる腐れ野郎、他に、いますかっていねーか、はは", id: "KwONQGM2AyLohkGOTF3u"}
1: {created_at: t, content: "初カキコ,ども...", id: "LIGRzMJJdxM1pJAo5R3L"}
length: 2
__proto__: Array(0)

ちゃんと入っている!!!これをcreated_atでsortすれば行けそうだ.

idFieldでidを取得するところがポイントです。

と書いてある通りに,doc.idがdoc.data()と並列で入っている!!


また,記事のNewTodoの通りに

const Add = () => {
  const [content, setContent] = useState('');
  const [pending, setPending] = useState(false);

  const add = async () => {
    setContent('');
    setPending(true);

    try {
      await ref.add({
        content,
        created_at: firebase.firestore.FieldValue.serverTimestamp(),
      });
    }
    finally {
      setPending(false);
    }
  }

useStateを使ってcontentを空のstr, pendingをfalseでstateとして初期化

そして追加btnが押された時のaddの処理を書く.

asyncを噛ませてcontentを空にし,実行中ということでpendingをtrueに

tryではawaitが使われるのでこちらが先になるのか?

setContent('')が行われていないのでcontentは残っている.これが先に refにcreated_atとともに追加される

そしてtryが終わった後にpendingをfalse, NOに書きかえる

その後async前半が処理されてinput valueのcontentが空になり pendingがfalseになる.

このaddを

  return (
    <div>
      <input 
        value = {content} 
        onChange={e => setContent(e.target.value)}
      />
      <button
        onClick={add}
      >
        Add
      </button>
        {pending && 'Pending...'}
    </div>

returnでinputを作り,valueには常にcontentを置き, onChangeにsetContentをしてe.target.valueをおく.

btnのonClickでaddがfireするように仕込み,

その下にはpendingがtrueの時のみ出るようにする

このComponentをAppで読み込むことによって

追加機能のあるinputとbtnが配備された.

Wesのよりかなりシンプルだ

どのcomponentでもrefは使っているので,Appで呼び出してpropsで渡そうか

しかしありえんほど簡単に


毎回firestoreをconsolelogで使用しているのもおかしいので改善策を感がてみた

config のままexportして,各自のcomponentでinitする作戦は

objのconfigをうまくconfigとしてexportできずにerror

import config from '../Config/config';

firebase.initializeApp(config);

これでうまくいきそうだが,これでもno -usedになってしまう

App側で済ますのも無理だった

これは仕方ないのかもしれない

f:id:kei_s_lifehack:20200514034048p:plain

export const firestore = firebase.initializeApp(config);

をconfig.jsに書いて

import {firestore} from '../Config/config';

をfirestore使う全てのcomponentに書くのは避けられないようだ;;;;;;

kaede-0902ch.web.app

timestamp 出ないけど大まかなレイアウトは下

sort

timestampの値でsortがしたい

[1, 2,3, ] ならarr.sortで簡単だがarrのobjが必要

created_atの中身は

created_at: t
nanoseconds: 964000000
seconds: 1589391378

である

これを普通に出そうとしたらめっちゃ詰まった

kei-s-lifehack.hatenablog.com

まぁ2020.05.21に解決して,例外処理挟んで出せるようになった, UIも書いた

f:id:kei_s_lifehack:20200521213413p:plain

ここで

React使っててなぜXSSが防げてるのかなんもわからん

dangerouslySetInnerHTMLを使うとXSSできるようになりますよ!() やれるもんならやってみて下さいよ! Add関数壊れてるわよ

f:id:kei_s_lifehack:20200521214339p:plain

おもちゃかコレェ!!!!!!!(言いたかっただけ)

www.youtube.com

動かしてなぜ動かないかわからん...

qiita.com

短くかける!!!と思ってここのsetTitleのところを流用してadd関数を作った

import React, { useState } from "react";
import {Col, Row,} from 'react-bootstrap';
import {Form} from 'react-bootstrap';
import {Button} from 'react-bootstrap';
import firebase from 'firebase/app';
import { firestore } from '../Config/config';



const ref = firebase.firestore().collection('writings');

const Add = () => {
  const [content, setContent] = useState('');
  const [pending, setPending] = useState(false);

  const add = async () => {
    setContent('');
    setPending(true);

    try {
      await ref.add({ 
        content: content,
        created_at: 
          firebase.firestore.FieldValue.serverTimestamp,
      });
    }
    finally {
      setPending(false);
    }
  }
  return (
    <div>
    <Form>
      <Row>
        <Col md = {7}>
          <Form.Control 
            placeholder='write here' 
            value = {content} 
            onChange={e => setContent(e.target.value)}
          />
        </Col>
        <Col md = {5}>
          <Button variant="primary" 
            type="submit" onClick={add}
            >
            Submit
          </Button>
        </Col>
      </Row>
    </Form>
    {pending && 'Pending...'}
    </div>
  )
};


export default Add;

これを自分のちんちんで...じゃなくて自分で入れてbuttton押すと, 動いているように見えるが中身が入らない

エラーも出ないしわからない....

最初は動いてたもん,自分で自分のちんちん舐めたいって入れないし...

そんなに身体が柔らかくないので...(そういう問題?)

firestore追加されない問題

2020.05.30. 解決を図る.

const ref = firebase.firestore().collection('writings');

const Add = () => {
  const [content, setContent] = useState('');
  const [pending, setPending] = useState(false);

  const add = async () => {
    setContent('');
    setPending(true);

    try {
      console.log('adding');
      await ref.add({ 
        content: content,
        created_at: 
          firebase.firestore.FieldValue.serverTimestamp,
      });
    }
    finally {
      setPending(false);
    }
  }

こうしてconsole.log addingは一瞬見える.

追加中に画面が切り替わっているのだろうか?

ちんちんが追加された時はそういえばBootstrapは使っていなかった

このBtnが何か悪いのだろうか

f:id:kei_s_lifehack:20200530045728p:plain