まず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を使ってみよう!!
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が変化するたびに「副作用」として処理を追加できるらしい
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のやり方はできないようだ
全部はわからんがここのコードを使ってみる
export const createWrintings = (writings) => {
return storeRef.add({
created: firebase.firestore.FieldValue.serverTimestamp(),
content: writings,
});
};
create, addは簡単に作れた.stateは使わないようだ
SHOWができないから
これを使ってみる
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に書き込めた
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側で済ますのも無理だった
これは仕方ないのかもしれない
export const firestore = firebase.initializeApp(config);
をconfig.jsに書いて
import {firestore} from '../Config/config';
をfirestore使う全てのcomponentに書くのは避けられないようだ;;;;;;
timestamp 出ないけど大まかなレイアウトは下
sort
timestampの値でsortがしたい
[1, 2,3, ] ならarr.sortで簡単だがarrのobjが必要
created_atの中身は
created_at: t nanoseconds: 964000000 seconds: 1589391378
である
これを普通に出そうとしたらめっちゃ詰まった
まぁ2020.05.21に解決して,例外処理挟んで出せるようになった, UIも書いた
ここで
React使っててなぜXSSが防げてるのかなんもわからん
dangerouslySetInnerHTMLを使うとXSSできるようになりますよ!() やれるもんならやってみて下さいよ! Add関数壊れてるわよ
おもちゃかコレェ!!!!!!!(言いたかっただけ)
動かしてなぜ動かないかわからん...
短くかける!!!と思ってここの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押すと, 動いているように見えるが中身が入らない
エラーも出ないしわからない....
最初は動いてたもん,自分で自分のちんちん舐めたいって入れないし...
そんなに身体が柔らかくないので...(そういう問題?)