Last active
February 5, 2022 08:27
Star
You must be signed in to star a gist
Starter settings for React (Web or Native) with TypeScript, ESLint, Prettier, and Apollo. Also, GraphQL, Bulma and Webfont Loader are included.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# dependencies | |
/node_modules | |
# testing | |
/coverage | |
# production | |
build/* | |
build | |
public/* | |
public | |
# misc | |
.DS_Store | |
.env.local | |
.env.development.local | |
.env.test.local | |
.env.production.local | |
npm-debug.log* | |
yarn-debug.log* | |
yarn-error.log* | |
src/react-app-env.d.ts | |
src/serviceWorker.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"env": { | |
"browser": true, | |
"commonjs": true, | |
"es6": true, | |
"node": true, | |
"jest": true, | |
"react-native/react-native": true | |
}, | |
"plugins": [ | |
"react", | |
"react-native", | |
"react-hooks", | |
"prettier", | |
"@typescript-eslint", | |
"jsx-a11y" | |
], | |
"extends": [ | |
"airbnb-typescript", | |
"plugin:react/recommended", | |
"plugin:@typescript-eslint/recommended", | |
"prettier/@typescript-eslint", | |
"prettier", | |
"prettier/react", | |
"plugin:prettier/recommended", | |
], | |
"parser": "@typescript-eslint/parser", | |
"parserOptions": { | |
"sourceType": "module", | |
"ecmaVersion": 2018, | |
"allowImportExportEverywhere": false, | |
"codeFrame": false, | |
"ecmaFeatures": { | |
"jsx": true | |
}, | |
"project": "./tsconfig.json" | |
}, | |
"settings": { | |
"react": { | |
"version": "detect" | |
}, | |
"import/resolver": { | |
"typescript": { | |
"alwaysTryTypes": true | |
} | |
} | |
}, | |
"rules": { | |
// React specifics | |
"react/jsx-key": "error", | |
"react/no-unused-prop-types": 0, | |
"react-hooks/rules-of-hooks": "error", | |
"react-hooks/exhaustive-deps": "warn", | |
"react/button-has-type": 0, | |
"react/jsx-filename-extension": ["off"], | |
"react/prop-types": "warn", | |
// ESLint specifics | |
"prefer-promise-reject-errors": ["off"], | |
"no-nested-ternary": "off", | |
"no-return-assign": ["off"], | |
"no-shadow": "off", | |
"no-lonely-if": "warn", | |
"consistent-return": "off", | |
"no-use-before-define": "warn", | |
"no-underscore-dangle": "off", | |
"no-unused-vars": "warn", | |
"import/no-unresolved": "off", | |
"no-unused-expressions": "off", | |
"radix": "off", | |
"spaced-comment": "off", | |
"jsx-a11y/alt-text": "warn", | |
"jsx-a11y/click-events-have-key-events": "warn", | |
"jsx-a11y/no-static-element-interactions": "warn", | |
"jsx-a11y/no-noninteractive-element-interactions": "warn", | |
"prettier/prettier": "error", | |
"arrow-parens": ["error", "always"], | |
"indent": "off", | |
"camelcase": "off", | |
// Typescript specifics | |
"@typescript-eslint/camelcase": [ | |
"error", | |
{ | |
"properties": "never", | |
"genericType": "never", | |
"ignoreDestructuring": true | |
} | |
], | |
"max-len": [ | |
"error", | |
{ | |
"code": 100 | |
} | |
], | |
"@typescript-eslint/no-unused-vars": [ | |
"warn", | |
{ | |
"vars": "all", | |
"args": "none" | |
} | |
], | |
"@typescript-eslint/no-explicit-any": [ | |
"error", | |
{ | |
"ignoreRestArgs": true | |
} | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"endOfLine": "lf", | |
"tabWidth": 4, | |
"printWidth": 100, | |
"trailingComma": "es5", | |
"semi": true, | |
"singleQuote": true, | |
"arrowParens": "always" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { ApolloProvider } from '@apollo/react-hooks'; | |
// Local Modules | |
import Main from './Components/Main'; | |
// Apollo client | |
import client from './Utils/withApolloClient'; | |
// <App /> Component | |
const App = () => { | |
return ( | |
<ApolloProvider client={client}> | |
<Main /> | |
</ApolloProvider> | |
); | |
}; | |
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fontsList: Array<any> = [ | |
{ | |
font: 'Roboto', | |
weights: [400, 500], | |
}, | |
{ | |
font: 'Teko', | |
weights: [500, 600], | |
}, | |
{ | |
font: 'Yanone Kaffeesatz', | |
weights: [400, 500], | |
}, | |
{ | |
font: 'Nunito', | |
weights: [400, 600, 700], | |
}, | |
]; | |
export default fontsList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { render } from 'react-dom'; | |
import WebFont from 'webfontloader'; | |
// Local Modules | |
import App from './App'; | |
// Styles | |
import './Styles/main.scss'; | |
// Google Fonts | |
WebFont.load({ | |
google: { | |
families: ['Roboto', 'Nunito'], | |
}, | |
}); | |
// Launch 🚀 | |
const root = document.getElementById('root'); | |
if (root !== null) { | |
render( | |
<React.StrictMode> | |
<App /> | |
</React.StrictMode>, | |
root, | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { PersistGate } from 'redux-persist/integration/react'; | |
import { Provider } from 'react-redux'; | |
import { ApolloProvider, ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client'; | |
import { createUploadLink } from 'apollo-upload-client'; | |
import { setContext } from '@apollo/client/link/context'; | |
import { HelmetProvider } from 'react-helmet-async'; | |
import GoogleFontLoader from 'react-google-font-loader'; | |
import { Lines } from 'react-preloaders'; | |
// Components | |
import MainGate from 'components/MainGate'; | |
// Store | |
import { store, persistor } from 'store/store'; | |
// Utils | |
import isDev from 'utils/devUtils'; | |
// Other | |
import fontsList from './data/fontsList'; | |
// Style | |
import 'styles/scss/main.scss'; | |
import 'slick-carousel/slick/slick.css'; | |
import 'slick-carousel/slick/slick-theme.css'; | |
import 'antd/dist/antd.css'; | |
// Apollo >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | |
// 0. Determine if dev or production | |
const appUri = isDev() ? process.env.REACT_APP_GQL_DEV_SERVER_URI : process.env.REACT_APP_GQL_PROD_SERVER_URI; | |
// 1. Prepare the URI | |
const httpLink = createUploadLink({ uri: appUri }); | |
// 2. Authorization, token | |
const authLink = setContext((_, { headers }) => { | |
const lsPrefix = process.env.REACT_APP_LS_PREFIX; | |
const token = localStorage.getItem(`${lsPrefix}app_token`); | |
return { | |
headers: { | |
...headers, | |
authorization: token ? `Bearer ${JSON.parse(token)}` : '', | |
}, | |
}; | |
}); | |
// 3. The client | |
const client = new ApolloClient({ | |
link: authLink.concat(httpLink), | |
cache: new InMemoryCache(), | |
connectToDevTools: isDev(), | |
}); | |
// The app >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | |
const App = (): React.ReactElement => { | |
return ( | |
<ApolloProvider client={client}> | |
<Provider store={store}> | |
<PersistGate loading={null} persistor={persistor}> | |
<HelmetProvider> | |
<GoogleFontLoader fonts={fontsList} /> | |
<MainGate /> | |
<Lines /> | |
</HelmetProvider> | |
</PersistGate> | |
</Provider> | |
</ApolloProvider> | |
); | |
}; | |
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import localforage from 'localforage'; | |
const lfConfig = () => { | |
localforage.config({ | |
driver: localforage.LOCALSTORAGE, | |
name: 'Betting', | |
version: 1, | |
storeName: 'BettingStore', | |
description: 'Local storage for Betting-App using localforage', | |
}); | |
}; | |
export default lfConfig; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Start it up | |
npx create-react-app my-app --template typescript | |
# or | |
yarn create react-app my-app --template typescript | |
// Typescript with ESLint and Prettier (DEV Dependencies) | |
yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser babel-eslint eslint eslint-config-airbnb-typescript eslint-config-airbnb eslint-config-prettier eslint-config-react-app eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-prettier eslint-plugin-react eslint-plugin-react-hooks prettier pretty-quick eslint-plugin-react-native | |
// If not used create-react-app with typescript above, you can also manually install along with others | |
yarn add typescript @testing-library/jest-dom @testing-library/react @ant-design/icons @types/jest @types/node @types/react @types/react-dom | |
// Creating the configs | |
touch .eslintignore .eslintrc .prettierrc .env .sample.env | |
// Apollo and GraphQL | |
yarn add @apollo/react-hooks apollo-boost graphql-tag graphql | |
// others | |
yarn add react-router-dom sass antd bootstrap@5.1.3 react-google-font-loader firebase | |
// Delete CRA unneeded files then create some dirs | |
rm src/logo.svg src/index.css src/App.css && cd src/ && mkdir styles components utils data assets api && cd components/ && mkdir app mainGate && cd ../styles/ && touch app.scss && cd ../utils/ && touch withApolloClient.ts && cd ../../ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; | |
import thunk from 'redux-thunk'; | |
import { persistStore, persistReducer } from 'redux-persist'; | |
import storage from 'redux-persist/lib/storage'; // default | |
import { composeWithDevTools } from 'redux-devtools-extension'; | |
import categories from './reducers/categoryReducer'; | |
import cards from './reducers/cardReducer'; | |
import users from './reducers/userReducer'; | |
// All reducers | |
const rootReducer = combineReducers({ | |
users, | |
}); | |
// Middleware: Redux Persist Config | |
const persistConfig = { | |
key: 'root', | |
storage, | |
}; | |
// Middleware: Redux Persist Persisted Reducer | |
const persistedReducer = persistReducer(persistConfig, rootReducer); | |
// This will prevent 'several store enhancers' error | |
// const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; | |
// Redux: Store | |
const store: any = createStore(persistedReducer, composeWithDevTools(applyMiddleware(thunk))); | |
// Middleware: Redux Persist Persister | |
const persistor = persistStore(store); | |
// Exports | |
export { store, persistor }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Take Note: | |
- react-app inside .eslintrc (plugins) won't work alongside TypeScript? I'm not sure with this one as well.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
// As of TypeScript 3.7.* this is the default | |
{ | |
"compilerOptions": { | |
"target": "es5", | |
"lib": [ | |
"dom", | |
"dom.iterable", | |
"esnext" | |
], | |
"allowJs": true, | |
"skipLibCheck": true, | |
"esModuleInterop": true, | |
"allowSyntheticDefaultImports": true, | |
"strict": true, | |
"forceConsistentCasingInFileNames": true, | |
"module": "esnext", | |
"moduleResolution": "node", | |
"resolveJsonModule": true, | |
"isolatedModules": true, | |
"noEmit": true, | |
"jsx": "react" | |
}, | |
"include": [ | |
"src" | |
] | |
} | |
// We need to add something to avoid 'some' errors | |
{ | |
"compilerOptions": { | |
"target": "es5", | |
"lib": [ | |
"dom", | |
"dom.iterable", | |
"esnext" | |
], | |
"downlevelIteration": true, | |
"allowJs": true, | |
"skipLibCheck": true, | |
"esModuleInterop": true, | |
"allowSyntheticDefaultImports": true, | |
"strict": true, | |
"forceConsistentCasingInFileNames": true, | |
"module": "esnext", | |
"moduleResolution": "node", | |
"resolveJsonModule": true, | |
"isolatedModules": true, | |
"noEmit": true, | |
"jsx": "react", | |
"noImplicitAny": false | |
}, | |
"include": [ | |
"src" | |
], | |
"exclude": [ | |
"node_modules" | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ApolloClient, { InMemoryCache } from 'apollo-boost'; | |
import gql from 'graphql-tag'; | |
// Apollo: GQLS | |
const LOCAL_MAIN_DEF_QUERY = gql` | |
query @client { | |
clickStat | |
identifierWrapper | |
trailerType | |
modalOn | |
} | |
`; | |
const LOCAL_MAIN_DEF_MUTATION = gql` | |
mutation LOCAL_DEF_MUTATION($obj: [String]) { | |
setDef(obj: $obj) @client | |
} | |
`; | |
// Query and Mutation | |
const resolvers = { | |
Mutation: { | |
setDef: (_root, args, { cache }) => { | |
// Get the new values | |
const { | |
obj: { modalOn, clickStat, identifierWrapper, trailerType }, | |
} = args; | |
// Get the current state | |
const existingData = cache.readQuery({ | |
query: LOCAL_MAIN_DEF_QUERY, | |
}); | |
// Prepare data | |
const newData = { | |
data: { | |
...existingData, | |
modalOn, | |
clickStat, | |
identifierWrapper, | |
trailerType, | |
}, | |
}; | |
// Save new data | |
cache.writeData(newData); | |
return newData; | |
}, | |
saveData: (_root, args, { cache }) => { | |
// type is just a identifier | |
// movArray is the movie array of objects | |
const { type, movArray } = args; | |
let newMovArray; | |
// Add __typename key, Apollo Client is strict | |
if (type !== 'heroMovData') { | |
newMovArray = movArray.map(v => ({ ...v, __typename: 'Movie' })); | |
} else if (type === 'heroMovData') { | |
newMovArray = { ...movArray, __typename: 'Movie' }; | |
} | |
// Prepare data | |
const data = { | |
data: { [args.type]: newMovArray }, | |
}; | |
// Save new data | |
cache.writeData(data); | |
return data; | |
}, | |
}, | |
}; | |
// TypeDefs | |
const typeDefs = gql` | |
type Movie { | |
original_title: String | |
} | |
`; | |
// Defaul Local States | |
const defaults = { | |
__typename: 'Defaults', | |
clickStat: '', | |
}; | |
// The Apollo client | |
const client = new ApolloClient({ | |
cache: new InMemoryCache(), | |
clientState: { | |
resolvers, | |
defaults, | |
typeDefs, | |
}, | |
}); | |
// export { }; | |
export default client; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment