React, the beginning

Para empezar:

https://www.w3schools.com/react/default.asp

https://ibaslogic.com/react-tutorial-for-beginners/

https://leanpub.com/reactjsforthevisuallearner/read#leanpub-auto-chapter-1–what-is-this-all-about

Para seguir:

https://fullstackopen.com/es/about

Hooks:

https://css-tricks.com/react-hooks-the-deep-cuts/

https://usehooks.com/

https://www.freecodecamp.org/news/react-hooks-fundamentals/

Ebook:

Reactjs_Succinctly

Cambiar borrado de registros

En .NET por defecto se eliminan los registros relacionados en cascada. Para evitarlo antes de actualizar la base de datos tenemos que cambiar la migración:

constraints: table =>
                {
                    table.PrimaryKey("PK_ProfesionalesActividades", x => x.Id);
                    table.ForeignKey(
                        name: "FK_ProfesionalesActividades_Actividad_ActividadId",
                        column: x => x.ActividadId,
                        principalTable: "Actividad",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_ProfesionalesActividades_Profesionales_ProfesionalId",
                        column: x => x.ProfesionalId,
                        principalTable: "Profesionales",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

Para que por defecto sea así en todas las relaciones lo tenemos que poner en el contexto:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    foreach (var foreignKey in modelBuilder.Model.GetEntityTypes()
        .SelectMany(e => e.GetForeignKeys()))
    {
        foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
    }
}

Y si la cosa ya está hecha añadimos una migración a mano:

In the Package Manager Console, create a new, empty migration with the Add-Migration command, then fill in the Up method like this:

        migrationBuilder.DropForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",
            table: "ElementsPerStrip");
        migrationBuilder.AddForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",
            table: "ElementsPerStrip",
            column: "StripId",
            principalTable: "Strips",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
For completeness, do the opposite in the Down method:

        migrationBuilder.DropForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",
            table: "ElementsPerStrip");
        migrationBuilder.AddForeignKey(
            name: "FK_ElementsPerStrip_Strips_StripId",
            table: "ElementsPerStrip",
            column: "StripId",
            principalTable: "Strips",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

Evitar ciclos en la API

builder.Services.AddControllers().AddJsonOptions(x =>
x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);

o

[JsonIgnore]

Deshabilitar CORS

using Microsoft.EntityFrameworkCore;
using Profesiones.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
builder.Services.AddDbContext<Contexto>(options =>
               options.UseSqlServer("Server=.\\SQLExpress;Database=Profesiones;Trusted_Connection=True;"));
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll",
        builder =>
        {
            builder
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader();
        });
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseCors("AllowAll");
app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Ejercicio typicode

Con la web https://jsonplaceholder.typicode.com/guide/ vamos a mostrar un selector de usuarios (con sus nombres) cuando seleccionemos uno nos mostrarán todos los ‘todos’ que tiene, cada uno tendrá a su lado un botón de editar y otro de borrar. También tendremos un botón de añadir un ‘todo’ a ese usuario.

Esperar foreach

function mostrarAmbasCartas(valueLocation, valueSpecies) {
			// document.querySelector(".alert").classList.toggle("visually-hidden");
			fetch("https://rickandmortyapi.com/api/location/"+valueLocation).then((response) => response.json()).then(async (data) => {
				console.log(data);
				if (data.residents.length>0) {
					console.log("anes foreach");
					await Promise.all(data.residents.map(async (element) => {
						await fetch(element).then((respuesta) => respuesta.json()).then((results) => {
							console.log(results);

							if (results.species==valueSpecies) {
								let carta=crearCarta(results);
								document.querySelector(".cartas").appendChild(carta);
								document.querySelector(".alert").classList.add("visually-hidden");
							}
						});
					}));

					console.log("fin foreach");

				} else {
					document.querySelector(".alert").classList.toggle("visually-hidden");
				}
			})
				.catch((err) => {
					console.log("Error: ", err);
				});
		}

Await vs then

async function showAvatar() {
			let img;
			// leer nuestro JSON
			fetch('https://es.javascript.info/article/promise-chaining/user.json')
				.then((response) => response.json())
				.then(res => {
					fetch(`https://api.github.com/users/${res.name}`)
						.then((response) => response.json())
						.then(result => {
							img=document.createElement('img');
							img.src=result.avatar_url;
							img.className="promise-avatar-example";
							document.body.append(img);
						});
				})


			// espera 3 segundos
			await new Promise((resolve, reject) => setTimeout(resolve, 3000));

			img.remove();

			//return githubUser;
		}
async function showAvatar() {

  // leer nuestro JSON
  let response = await fetch('/article/promise-chaining/user.json');
  let user = await response.json();

  // leer usuario github
  let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
  let githubUser = await githubResponse.json();

  // muestra el avatar
  let img = document.createElement('img');
  img.src = githubUser.avatar_url;
  img.className = "promise-avatar-example";
  document.body.append(img);

  // espera 3 segundos
  await new Promise((resolve, reject) => setTimeout(resolve, 3000));

  img.remove();

  return githubUser;
}