This file is for personal use and public use for anyone who reads it, it has points that it is useful for me in particular to leave written down in some accessible place while I do the bootcamp.
npm create vite@latest {NAMEOFTHEPROJECT} -- --template react
npm i --save-dev PACKAGE_NAME
npm install -g npm-check-updates
npm-check-updates
ncu -u
npm audit
const result = condition ? val1 : val2Explanation: result is where val1 or val2 will be deposited, which val will be deposited in result depends on condition, if condition is true result=val1, otherwise result=val2.
const person = { name: name, age: age } === const person = { name, age }const numbers = [1, 2, 3];
const new_numbers = [...numbers, 4, 5];
console.log(new_numbers); // Print "[1, 2, 3, 4, 5]"
const numbers = [1, 2, 3];
const new_numbers = [numbers, 4, 5];
console.log(new_numbers); // Print "[[1, 2, 3], 4, 5]"<Greeting firstName='Arto' lastName='Hellas' />
const person = {
firstName: 'Arto',
lastName: 'Hellas'
}
<Greeting {...person} />> a
{ a: 2, b: 5 }
> b
{ b: 7, c: 8 }
> {...a, ...b}
{ a: 2, b: 7, c: 8 }-Add to vite.config.js:
export default defineConfig({
plugins: [react()],
server: {
proxy: {
' {URLTOACCESS} ': {
target: ' {URLTOREDIRECT} ',
changeOrigin: true,
},
}
},
})MongoDB Atlas Database : https://www.mongodb.com/es/atlas/database
0.0.0.0
const mongoose = require('mongoose');
const logger = require('./logger');
const config = require('./config');
const db_url = `mongodb+srv://${config.DB_USERNAME}:${config.DB_PASSWORD}@cluster0.ythuy5f.mongodb.net/${config.DB_DATABASE}?retryWrites=true&w=majority&appName=Cluster0`;
const setup_db = () => {
mongoose.set('strictQuery', false);
process.on('exit', () => turn_off());
// console.log('Connecting to', db_url);
return mongoose.connect(db_url).then((result) => result ? logger.info('[i] DB connected.') : logger.info('[!] Can\'t connect to the DB.'));
};
const turn_off = () => {
logger.info('[i] DB disconnected.');
mongoose.connection.close();
};
module.exports.setup_db = setup_db;
module.exports.turn_off = turn_off;const mongoose = require('mongoose');
const blogSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: String,
url: {
type: String,
required: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
likes: Number
});
module.exports = mongoose.model('Blog', blogSchema); //Generate the modelThe populate('blogs') function tells Mongoose to search the collection of related blogs and replace the blogs in the field.
app.use('/api/login', loginRouter);const loginRouter = require('express').Router();
loginRouter.post('/', async (request, response) => {...};
loginRouter.get('/users', async (request, response) => {...};
//...
module.exports = loginRouter;That's possible with the express-async-errors library which automatically execute "next" function when there is an error
// in the app file
require('express-async-errors');https://deadsimplechat.com/blog/react-toastify-the-complete-guide/
npm install --save-dev vitest jsdom
npm install --save-dev @testing-library/react @testing-library/jest-dom
npm install --save-dev eslint-plugin-vitest-globals
npm install --save-dev @testing-library/user-event-Config the .eslintrc.cjs:
Add to env:
bash "vitest-globals/env": true
-Add to extends:
bash 'plugin:vitest-globals/recommended',
-And finally for run tests:
bash npm test -- --coverage / bun vitest
-Create and add content to vitest.config.ts:
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
test: {
globals: true,
environment: 'jsdom',
},
plugins: [react({
jsxRuntime: 'automatic'
})],
});It is a pure function that receives the current state and an action object. If there is a state change, the old object does not change, but is replaced by a new object.
- https://redux.js.org/tutorials/essentials/part-1-overview-concepts#reducers
- https://es.wikipedia.org/wiki/Programaci%C3%B3n_funcional#Funciones_puras
- React Query is a server state library, responsible for managing asynchronous operations between the server and client
- Redux, etc. are client state libraries that can be used to store asynchronous data, although less efficiently when compared to a tool like React Query
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import ReactDOM from 'react-dom/client';
import App from './App';
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById('root')).render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
);I add QueryClient and QueryClientProvider, initialize queryClient and enclose inside QueryClientProvider with client=queryClient initialized above
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
import anyService from './../../services/anyservice';
const queryClient = useQueryClient();
const Component () => {
const updateAny = () => {
queryClient.invalidateQueries(['any']);
};//invalidate
const result = useQuery({
queryKey: ['any'],
queryFn: anyService.getAll
});//Only once unless invalidated
if(result.isLoading)
{
return (
<div>
<h1>Loading any...</h1>
</div>
);
}
if(result.isError)
{
return (
<div>
<h1>Any service not avaible due to problem in server.</h1>
</div>
);
}
return (
<div>
<ul>
{result.data.map((any) => (
<li>{any}<li/>
))}
</ul>
</div>
);
}The good thing about this is that you can call the query and modify it from anywhere in the code without passing anything as an argument, just importing useQueryClient
onSuccess: (newAnecdote) => {
const anecdotes = queryClient.getQueryData(['anecdotes']);
queryClient.setQueryData(['anecdotes'], anecdotes.map(anecdote => anecdote.id === newAnecdote.id ? newAnecdote : anecdote));
}onSuccess: (newAnecdote) => {
const anecdotes = queryClient.getQueryData(['anecdotes']);
queryClient.setQueryData(['anecdotes'], anecdotes.concat(newAnecdote));
}import { createContext, useReducer } from 'react';
const anyReducer = (state, action) => {
switch (action.type) {
case 'ANY_NAME_FOR_THE_ACTION':
return any_value;//any value is the new state, because is a reducer function
default:
return state;
}
};
const AnyContext = createContext();
export const AnyContextProvider = (props) => {
const [any, anyDispatch] = useReducer(anyReducer, null);
return (
<AnyContext.Provider value={[any, anyDispatch]}>
{props.children}
</AnyContext.Provider>
);
};
import { useContext } from 'react';
export const useAnyValue = () => {
const anyAndDispatch = useContext(AnyContext);
return anyAndDispatch[0];
};
export const useAnyDispatch = () => {
const anyAndDispatch = useContext(AnyContext);
return anyAndDispatch[1];
};
export default AnyContext;import { AnyContextProvider } from './context/any';
const App = () => {
return (
<div>
<ToastContainer />
<AnyContextProvider>
<Navbar />
<BlogList />
</AnyContextProvider>
</div>
);
};
export default App;import { useAnyValue } from '../../../../context/user';
const any = useAnyValue();
console.log(any);import { useAnyDispatch } from '../../../../context/user';
const dispatch = useAnyDispatch();
dispatch({type: 'ANY_NAME_FOR_THE_ACTION', payload: {any: 'any'}});This updates itself
const useField = (type) => {
const [value, setValue] = useState('')
const onChange = (event) => {
setValue(event.target.value)
}
return {
type,
value,
onChange
}
}
const App = () => {
const name = useField('text')
// ...
return (
<div>
<form>
<input
type={name.type}
value={name.value}
onChange={name.onChange}
/>
// ...
</form>
</div>
)
}- Babel is a transpiler to convert new Javascript code into "old" Javascript code compatible with browsers, through presets that are collections of plugins (which are Babel extensions that modify the code in a specific way either for compatibility, optimization or another objective) In react use preset-react and for the new features of Javascript preset-dev
https://github.com/date-fns/date-fns