$ yarn create react-app instagram
$ yarn add date-fns
$ yarn add firebase
$ yarn add react-loading-skeleton
📁public에서 favicon.ico, index.html 파일만 남기고
📁src에서 App.js, index.js 파일만 남기고 정리한다
폴더를 아래 구조와 같이 생성해 준다
📁public
- 📁images
- 📁avatars
- 📁users
📁public
- 📄index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Instagram</title>
<style>
body {
background-color: #fafafa;
}
</style>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
📁src
- 📄App.js
function App() {
return (
<p>Hello</p>
);
}
export default App;
📁src
- index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
📁src
- 📁components
- 📁constants
- 📁context
- 📁helpers
- 📁hooks
- 📁lib
- 📁pages
- 📁services
- 📄seed.js
📁src
- 📄seed.js
/* eslint-disable no-plusplus */
// NOTE: replace 'NvPY9M9MzFTARQ6M816YAzDJxZ72' with your Firebase auth user id (can be taken from Firebase)
export function seedDatabase(firebase) {
const users = [
{
userId: 'NvPY9M9MzFTARQ6M816YAzDJxZ72',
username: 'karl',
fullName: 'Karl Hadwen',
emailAddress: 'karlhadwen@gmail.com',
following: ['2'],
followers: ['2', '3', '4'],
dateCreated: Date.now()
},
{
userId: '2',
username: 'raphael',
fullName: 'Raffaello Sanzio da Urbino',
emailAddress: 'raphael@sanzio.com',
following: [],
followers: ['NvPY9M9MzFTARQ6M816YAzDJxZ72'],
dateCreated: Date.now()
},
{
userId: '3',
username: 'dali',
fullName: 'Salvador Dalí',
emailAddress: 'salvador@dali.com',
following: [],
followers: ['NvPY9M9MzFTARQ6M816YAzDJxZ72'],
dateCreated: Date.now()
},
{
userId: '4',
username: 'orwell',
fullName: 'George Orwell',
emailAddress: 'george@orwell.com',
following: [],
followers: ['NvPY9M9MzFTARQ6M816YAzDJxZ72'],
dateCreated: Date.now()
}
];
// eslint-disable-next-line prefer-const
for (let k = 0; k < users.length; k++) {
firebase.firestore().collection('users').add(users[k]);
}
// eslint-disable-next-line prefer-const
for (let i = 1; i <= 5; ++i) {
firebase
.firestore()
.collection('photos')
.add({
photoId: i,
userId: '2',
imageSrc: `/images/users/raphael/${i}.jpg`,
caption: 'Saint George and the Dragon',
likes: [],
comments: [
{
displayName: 'dali',
comment: 'Love this place, looks like my animal farm!'
},
{
displayName: 'orwell',
comment: 'Would you mind if I used this picture?'
}
],
userLatitude: '40.7128°',
userLongitude: '74.0060°',
dateCreated: Date.now()
});
}
}
firebase 설정
https://console.firebase.google.com/
프로젝트 생성 후
Firestore Database -> 데이터베이스 만들기
개발 규칙/운영 규칙은 아래와 같지만
현재는 개발 규칙을 그대로 사용한다
// development rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.time < timestamp.date(2022, 9, 3);
}
}
}
// production rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow write: if request.auth.uid != null;
}
}
}
Authentication -> 시작하기
Sign-in method 이메일/전화번호 사용 설정
참고로 firebase 9 버전 이상이다
firebase: "^9.9.1"
📁src
- 📁context
- 📄firebase.js
import { createContext } from 'react';
const FirebaseContext = createContext(null);
export default FirebaseContext;
📁src
- 📁lib
- 📄firebase.js
import Firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
// here I want to import the seed file
const config = {};
const firebase = Firebase.initializeApp(config);
const { FieldValue } = Firebase.firestore;
// here is where I want to call the seed file (only ONCE!)
// seedDatabase(firebase);
export { firebase, FieldValue };
📁src
- 📄index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import FirebaseContext from './context/firebase';
import { firebase, FieldValue } from './lib/firebase';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<FirebaseContext.Provider value={{ firebase, FieldValue }}>
<App />
</FirebaseContext.Provider>
);
프로젝트 개요->설정 버튼->프로젝트 설정
하단에 내 앱-> </> 클릭한다
앱 닉네임을 입력해 주고 앱 등록 버튼을 누르면
아래와 같이 뜰 거고 firebaseConfig에 있는 내용을 복사해서
📁lib
- 📄firebase.js
config를 채워준다
const config = {
apiKey: "",
authDomain: "",
projectId: "i,
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
그리고 seed.js 파일에 있는 데이터를 넣어줘야 한다
추가 주석이 달려있는 코드 두 줄을 추가하고 seed.js 파일에 있는 데이터를 firebase DB에 최초 한 번 밀어넣은 후
코드는 다시 주석 처리해 준다
import Firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
// here I want to import the seed file
import { seedDatabase } from '../seed'; // 추가
const config = {
// 채워준다
};
const firebase = Firebase.initializeApp(config);
const { FieldValue } = Firebase.firestore;
// here is where I want to call the seed file (only ONCE!)
seedDatabase(firebase); // 추가
export { firebase, FieldValue };
$ yarn add react-router-dom
"react-router-dom": "^6.3.0",
react-router-dom이 버전 6이고
버전 6에서는 Switch를 지원하지 않는다 Switch -> Routes로 바뀌었다
또한 component->element로 바꼈다.
📁pages
- 📄login.js
export default function Login() {
return(
<p>Login Page</p>
);
}
📄App.js
import { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
const Login = lazy(() => import ('./pages/login'));
function App() {
return (
<Router>
<Suspense fallback={<p>Loading...</p>}>
<Routes>
<Route path="/login" element={<Login />} />
</Routes>
</Suspense>
</Router>
);
}
export default App;
📁constants
- 📄routes.js
export const DASHBOARD = '/';
export const LOGIN = '/login';
export const SIGN_UP = '/signup';
export const PROFILE = '/p/:username';
export const NOT_FOUND = '/not-found';
📄App.js
import { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import * as ROUTES from './constants/routes'; // 추가
const Login = lazy(() => import ('./pages/login'));
function App() {
return (
<Router>
<Suspense fallback={<p>Loading...</p>}>
<Routes>
<Route path={ROUTES.LOGIN} element={<Login />} /> // 수정
</Routes>
</Suspense>
</Router>
);
}
export default App;
📁pages
- 📄login.js
기존에 react-router-dom 6 버전 미만에서 사용하던 useHistory은 useNavigate로 바뀌었다
import { useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import FirebaseContext from '../context/firebase';
export default function Login() {
const navigate = useNavigate();
const { firebase } = useContext(FirebaseContext);
const [emailAddress, setEmailAddres] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const inInvalid = password === '' || emailAddress === '';
const handleLogin = () => {};
useEffect(() => {
document.title = 'Login - Instagram';
}, [])
return(
<p>Login Page</p>
);
}
$ yarn add tailwindcss -D
$ yarn add prop-types -D
$ yarn add postcss-cli -D
$ yarn add npm-run-all -D
$ yarn add autoprefixer -D
$ yarn add postcss -D
$ yarn install
📄packages.json
"scripts": {
"build:css": "postcss src/styles/tailwind.css -o src/styles/app.css",
"watch:css": "postcss src/styles/tailwind.css -o src/styles/app.css --watch",
"react-scripts:start": "sleep 5 && react-scripts start",
"start": "run-p watch:css react-scripts:start",
"build": "run-s build:css react-scripts:build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
📁styles
- 📄tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;
$ yarn start
📁styles에 📄app.css 파일이 생성될 것이다
📁src
- 📄index.js
import './styles/app.css'; // 추가
📁pages
- 📄login.js
import { useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import FirebaseContext from '../context/firebase';
export default function Login() {
const navigate = useNavigate();
const { firebase } = useContext(FirebaseContext);
const [emailAddress, setEmailAddres] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const inInvalid = password === '' || emailAddress === '';
const handleLogin = () => {};
useEffect(() => {
document.title = 'Login - Instagram';
}, [])
return( // 아래 부분 수정
<div className="container flex mx-auto max-w-screen-md items-center h-screen">
<p>I Hava no idea!</p>
</div>
);
}
📄postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
📄tailwind.config.js
module.exports = {
content: ["./src/**/*.{html,js}"],
future: {
removeDeprecatedGapUtilities: true
}
}
postcss + tailwind 조합 설정은 아래 사이트를 참고하면 된다
https://tailwindcss.com/docs/installation/using-postcss
아래 이미지와 같이 텍스트가 중앙으로 옮겨졌다면 설정 완료!
https://www.youtube.com/watch?v=mDgEqoQUBgk
'React&React-Native > React' 카테고리의 다른 글
[#. React] react-scripts 4.0.3 사용으로 인한 에러 해결 (0) | 2022.08.29 |
---|---|
[#. React] React+Typescript+Tailwind CSS 프로젝트 초기 세팅하기 (0) | 2022.08.17 |
[#. React] react-scripts: Permission denied 해결하기 (0) | 2022.05.06 |
[#. React] React 18 새롭게 추가된 기능 알아보기 (0) | 2022.01.13 |
[#. React] jest를 이용해서 test 하기 (0) | 2021.11.29 |