A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Contando y buscando TODOs

10/23
Recursos

Aportes 81

Preguntas 12

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

馃挌 Like si quieres un Curso de Optimizaci贸n, Rendimiento y Debugging en React.js para profundizar much铆simo m谩s en c贸mo funcionan los renders y re-renders con React.

Con !, es es negativo
Con !!, es positivo porque niegas al que esta negando y termina siendo positivo

En realidad no necesita el doble !, ya que colocando solo todo.completed filtrar谩 a los que sean true, colocando !! es como colocar !!! ya que todos se eliminan

Juan, ser铆a genial que hicieras los mismo que anda haciendo Jonathan Alvarez con los cursos de Next.js.

Es decir toda una familia de cursos de React para poder aprender todo lo que sea posible, y ojal谩 que fueras tu el que lo hiciera, tenes mucho talento, crack.

Por finnn, gracias a Juan supe de una manera clara como hacer un buscador sencillo y sin tanta complicaci贸n. Que clase maestra. Aqu铆 dejo mi ejemplo puesto en pr谩ctica. https://apebogota.com/#empleo

BRUTAL esta clase, me encant贸 pero, hay que ver un par de veces para absorber todo lo nuevo que se da. Excelente realmente.

Hola 馃榾

comparto una manera para el filtro

const filterTodos = todos.filter((todo) => {
    return todo.text.toLowerCase().includes(searchValue.toLowerCase());
  });

componente

<TodoList>
        {filterTodos.map((item, i) => (
          <TodoItem key={i} {...item} />
        ))}
 </TodoList>


Probaron con 4 o m谩s signos de exclamaci贸n

const completedTodos = todos.filter((todo) => !!!!todo.completed).length;

PD:

1.- Niega, 2. Niega el anterior, 3. Niega el anterior y as铆鈥

Soy tan distra铆do que me avent茅 media hora viendo videos de la llorona en YouTube mientras ve铆a la clase.

8.-Contando y buscando TODOs

Combinando el estado con las props podremos enviar desde el componente padre la informaci贸n del estado y como actualizarlo a todos nuestros componentes. De esta manera los componentes hijos le comunicaran al padre que debe actualizar el estado cuando sea necesario y cuando esto suceda, el padre comunicara el cambio a los dem谩s hijos as铆 toda la app podr谩 reaccionar a las interacciones de los usuarios.

Cada vez que se cambia el estado se hace render (re-render) con la nueva info, pero como se llama a varios componentes no solo ser谩 un re-render sino varios. Hay que tener mucho cuidado con eso.

Ver茅 esta clase todas las veces que sean necesarias hasta entenderla. La explicaci贸n es buena, pero por alguna raz贸n no logro asimilar el algoritmo.

Yo filtr茅 los Todos de la siguiente manera:

const todosFiltered = todos.filter(todo => todo.text.toLowerCase().includes(searchValue.toLowerCase()));

Queda mucho m谩s compacto y no es necesario hacer la validaci贸n inicial del largo puesto que include si le pasas una cadena vac铆a te muestra todos.

Digo yo que si el contrario del contrario de verdadero es verdadero, podemos dejarlo como todo.completed en lugar de !!todo.completed 馃槃

Juan es un excelente Tutor. La l贸gica de React resulta super sencilla con su explicaci贸n.

Como solucion al segundo reto antes de pasar a la siguiente clase esta es mi solucion para actualizar el estado de un todo y como eliminaria un todo de la lista.

  1. Paso al componente TodoItem metiante la props el estado de todos y setTodos
  1. Luego desde el componente TodoItem, al hacer click sobre los iconos de accion y gracias a las funciones creadas en clases anteriores para marcar completado un todo use el metodo map de los array y luego actualice el estado de los todos con el metodo setTodos() el todo y para eliminar use el metodo filter y de igual manera el resultado lo envie a setTodos()

Dios mio, lo logr茅 que felicidad siento en este momento 馃槶

const [completedTodo, setCompletedTodo] = React.useState(props.completed)

    const onComplete = () => {
        setCompletedTodo(!completedTodo);
    }

// El elemento quedar铆a as铆 

<span 
            onClick={onComplete} 
            className={`Icon Icon-check ${completedTodo && 'Icon-check--active'}`}
            >
                鈭
            </span>

que fascinante esta clase y lo bien que ense帽a Juan!

Con este Plugin pueden usar comandos para crear el template autom谩ticamente del state
solo colocando:

us /// Enter


Tambi茅n ue para crear un useEffect 馃槃

Importante: La version de Yoelvis M, es la unica que he visto que hace esto

Quiero decir que dure dos hrs trabado porque me decia error, y en la declarion de

function TodoSearch([searchValue, setSearchValue]) { 
...

Use corchetes ( '[ 鈥 鈥榏鈥 ) en lugar de llaves ( 鈥榹鈥 鈥榼鈥 ) cuidado con tales typos y hagan uso de git diff

Aqu铆 el reto del ejercicio 馃コ

Hice una peque帽a funci贸n para que cuente los todos respecto a su estado mediante reduce, espero les sirva 馃槂

const todosByState = todos.reduce((prev,curr) => {
    if (curr.completed) prev.completed += 1
    else prev.incomplete += 1

    return prev;

  }, {completed: 0, incomplete: 0});

Hola Amigos como complemento se puede agregar un metodo para limpiar el input de busqueda al teclear 鈥楨SC鈥 de todos de la siguiente manera:

function TodoSearch({ searchValue, setSearchValue }) {
  const onSearchValueChange = (event) => {
    setSearchValue(event.target.value);
  };

  const handleKeyDown = (event) => {
    event.keyCode === 27 && setSearchValue("");
  };

  return [
    <input
      className="TodoSearch"
      placeholder="Cebolla"
      value={searchValue}
      onChange={onSearchValueChange}
      onKeyDown={handleKeyDown}
    />,
    <p>{searchValue}</p>,
  ];
}```

Para filtrar la busqueda use esto

  searchedTodos = !searchValue.length?todos:todos.filter(todo => todo.text.toLowerCase().includes(searchValue.toLowerCase()));

My filter solution, I hope it will be useful to you

if (!searchValue.length >= 1) {
    filteredTodos = todos;
  } else {
    filteredTodos = todos.filter((todo) => {
      return todo.text.toLowerCase().match(searchValue.toLowerCase());
    })
  }

De los mismos creadores de Misa de media noche, en este verano, llega, Llorar con la llorona!. S贸lo en React.

Tambi茅n se pod铆a hacer con el :

if (!searchValue)

Saber como React maneja los estados hace que ame m谩s Svelte 馃А.
Igualmente se ve interesante la librer铆a, veremos si los de Facebook crean el compilador para React para efectivamente ser reactivo.

esto es oro puro

Me encantaron los retos de esta clase :3

.
El primero no lo comparto porque veo que todos usamos la misma logica, enhorabuena. 馃槈

.
El segundo me sirvio mucho para comprender mejor como funciona el estado:

yo lo simplifique todo en una asola linea:

const filteredTodos = defaultTodos.filter((todo) => todo.text.toLowerCase().includes(search.toLowerCase()));

Con respecto al reto del final, yo crearia un estado con useState con la opcion completed y setCompleted, luego se las pasaria al componente item como props y desde las props ya crearia una funcion dentro del todoItem que cambie el estado con setCompleted(!completed)

Comparto un recurso para entender un poco mejor la informaci贸n sobre useState =

Soluci贸n al reto:

const todosFilter = todos.filter(todo => todo.text.toLowerCase().includes(searchValue.toLowerCase()));

.
y remplazar aqu铆:

<TodoList>
{
   todosFilter.map(todo => (
      <TodoItem 
         key={todo.text} 
         text={todo.text} 
         completed={todo.completed} 
      />
   ))
}
</TodoList>

.
Resultado:

Les comparto un poco de lo que he investigado, me cost贸 un poco entender el tema asi que espero les despeje unas dudas

Uso de informaci贸n en React.

Normalmente cuando creamos una aplicaci贸n sin React estamos acostumbrados a usar eventListeners, desde un archivo JavaScript, y en ocasiones pasar la funci贸n en HTML, utilizando sus atributos de eventos ( onclick=鈥渇uncionX()鈥 ) en React la forma de trabajar es similar a lo 煤ltimo pero debemos tomar en cuenta algunas cosas, primero la informaci贸n va de padres a hijos, los hijos no saben que tienen padre, pero si saben que les llega informaci贸n, debido a esto debemos manejar la l贸gica de sus eventos en un elemento padre, por lo que a los hijos solos les llegar谩 la funci贸n por medio de las props.

function App() {
 
  const searchValue = (event) => {
    console.log(event);
  };
 
  return (
    <div className="App">
      <div className="contenedor-principal">
          <h1>ToDo list</h1>
          <div className="contenedor-lista-tareas">
            <TodoCounter />
             <TodoSearch searchValue={searchValue}/>
            <TodoList>
              {
                todos.map(todo => 
                  <TodoItem
                    text={todo.text}
                    completed={todo.completed}
                    key={todo.id}
                    id={todo.id} />
                )
              }
            </TodoList>
            <CreateTodoButton /> 
          </div>
      </div>
    </div>
  );
}

En este ejemplo el componente 鈥<TodoSearch />鈥 esta recibiendo una funci贸n en una prop, llamada 鈥渟earchValue鈥, por lo que ahora sabe el valor que tendr谩 esa prop. Entonces dentro del componente:

const TodoSearch = ({searchValue}) => {
  
  return (
    <label htmlFor="name">
      <input type="text" 
             placeholder='Busca una tarea...' 
             id="name"
             onChange={searchValue} />
    </label>
  );
}

serchValue ser谩 la funci贸n que se ejecute en el evento 鈥渙nchange鈥, aqu铆 podemos notar varias cosas:

  • Es posible mandar funciones a elementos hijos, estos no saben de donde provino dicha funci贸n pero saben que tienen que ejecutar.

  • Tendremos que trabajar en un elemento padre si es necesario trabajar informaci贸n que solo tenemos disponible en otro archivo, por lo general la trabajamos en archivo que contiene la App completa pues quien tiene conocimiento de los componentes que la forman, no conoce los hijos de otros componentes pero si los props que tienen dichos componentes.

const searchResult = searchValue.length === 0 ? todos :
  todos.filter(item => item.text.toLowerCase().includes(searchValue.toLowerCase()))


buscando y completando los todos

comparando todos

Gracias Juan comprend铆 de una manera muy practica de poder hacer algo que me hab铆a complicado antes.

Admito que fue una buena clase.

As铆 resolv铆 el reto, asegurandome de que los string fueran minusculas y si est谩 vacio devuelve los todos.


  const [filter, setFilter] = useState('')
  const [todos, setTodos] = useState(defaultTodos)

const filterTodos = () => {
    return todos.filter(el => el.text.toLocaleLowerCase().includes(filter.toLocaleLowerCase())) || todos
  }

para el segundo reto utilic茅 un map

export default function TodoItem ({ text, completed, todos, setTodos }) {
  const handlerClick = () => {
    const newList = todos.map(el => {
      if (!(el.text === text)) {
        return el
      }
      el.completed = !el.completed
      return el
    })
    setTodos(newList)
  }

  return (
    <li className='Todo-Item'>
      <span
        onClick={handlerClick}
        className={`Icon Check ${completed && 'Check--active'}`}
      ></span>
      <p className={`Todo-text ${completed && 'Todo-active'}`}>{text}</p>
      <span className='Icon Close'>X</span>
    </li>
  )
};
import React from "react";
import { TodoCounter } from "./TodoCounter";
import { TodoSearch } from "./TodoSearch";
import { TodoList } from "./TodoList";
import { TodoItem } from "./TodoItem";
import { CreateTodoButton } from "./CreateTodoButton";
//import './App.css';

const defaultTodos=[
  {text: "Cortar cebolla", completed: true},
  {text: "ir al curso de react", completed: false},
  {text: "picar cebolla", completed: true},
  {text: "lalalal", completed: false}
]

function App() {

  const [todos, updateTodo] = React.useState(defaultTodos)
  const [searchValue, setSearchValue] = React.useState('')

  const completedTodo = todos.filter(todo=>todo.completed).length
  const totalTodos = todos.length

  let searchedTodo = []

  if (!searchValue.length >=1){
    searchedTodo = todos
  }else{
    searchedTodo = todos.filter(todo=>{
      const todoText = todo.text.toLowerCase()
      const searchedText = searchValue.toLowerCase()
      return todoText.includes(searchedText)
    })
  }

  return (
  <React.Fragment>
      <TodoCounter
        completed={completedTodo}
        total = {totalTodos}
      />
      <TodoSearch
        searchValue={searchValue}
        setSearchValue={setSearchValue}
      />      
      <TodoList>
        {searchedTodo.map(todo =>(
          <TodoItem 
          key={todo.text} 
          text={todo.text}
          completed={todo.completed}
          />
        ))}
      </TodoList>
      <CreateTodoButton/>
  </React.Fragment>
  );
}

export default App;

Me encanta la energia del profe 鉂わ笍

Mi filtrado es el siguiente:

  const filtro = todos.filter(ele => ele.text.toLowerCase().includes(searchValue.toLowerCase()))

y ya est谩, funciona perfectamente, si no escribes nada se muestran todos los TODOs, ahora solo faltar铆a enviar la constante filtro al componente TodoList para que muestre los TODOs que ha almacenado el filtro

Hice el reto de filtrado de la siguiente manera:

  const filterTodos = todos.filter(todo => todo.text.includes(searchValue))

<TodoList>
        {filterTodos.map(todo => (
          <TodoItem
            key={todo.text}
            text={todo.text}
            completed={todo.completed}
            />
        ))}

Haciendo una lista filtrada seg煤n el searchValue y despu茅s pasando esa lista para renderizar

Excelente explicaci贸n super f谩cil de entender

Imaginate hacer esto en javascript vainilla 馃拃馃拃

Una forma m谩s f谩cil de filtrar las tareas es esta鈥 simplemente definiendo la variable tasks de tipo let, para poder cambiar su valor con respecto a la b煤squeda que el usuario coloque.

let [tasks, setTasks] = React.useState(defaultTasks)
// filtro
tasks = tasks.filter(t => t.text.toUpperCase().includes(searchValue.toUpperCase()))
<TodoList>
  {todos.filter(todo => todo.text.toLowerCase().includes(searchValue.toLowerCase())).map(filteredSearch => (
    <TodoItem
      key={filteredSearch.text}
      text={filteredSearch.text}
      completed={filteredSearch.completed}
    />
  ))}
</TodoList>

Cabe resaltar que la forma en que viajan los datos es que lo componentes anidados desencadenan eventos, que cuando son recibidos por el componente padre, este hace las veces de orquestador, enviando el cambio a otro componente que lo necesite.

// App.tsx

type todoType = {
  text: string;
  completed: boolean;
};

const defaultTodos: todoType[] = [
  { text: "Crear smart app", completed: true },
  { text: "Lavar loza Lorem ipsum in dolor sit amet", completed: true },
  { text: "Mirar las plantas", completed: true },
  { text: "Mirar las plantas Lorem ipsum in dolor sit amet", completed: false },
];

function App() {
  const [todos, setTodos] = useState<todoType[]>(defaultTodos);
  const [searchValue, setSearchValue] = useState<string>('');
  
  const completedTodos = todos.filter((todo) => todo.completed === true).length;
  const totalTodos = todos.length;

  let searchedTodos = []; 
  if (!(searchValue.length >= 1)) {
    searchedTodos = todos;
  } else {
    searchedTodos = todos.filter((todo) => {
      const todoText = todo.text.toLowerCase();
      const searchText = searchValue.toLowerCase();
      return todoText.includes(searchText);
    })
  }

  return (
    <div className="App max-w-lg mx-auto flex flex-col justify-center">
      <TodoCounter completed={completedTodos} total={totalTodos}/>
      <TodoSearch searchValue={searchValue} setSearchValue={setSearchValue} />
      <TodoList>
        {searchedTodos.map((todo) => (
          <TodoItem
            key={todo.text}
            text={todo.text}
            completed={todo.completed}
          />
        ))}
      </TodoList>
      <CreateTodoButton />
    </div>
  );
}

.

// todo-counter.tsx
type completedTypes = {
  completed: number;
  total: number;
};

const TodoCounter = ({ completed, total }: completedTypes) => {
  return (
    <div className="p-6">
      <h2 className="text-3xl font-bold">Tareas</h2>
      <p className="text-xl text-center">Has completado <b>{`${completed} de ${total}`}</b> tareas</p>
    </div>
  );
};

.

// todo-search.tsx
const TodoSearch = ({ searchValue, setSearchValue })=> {
  const onSearchEvent = (event: any) => setSearchValue(event.target.value)

  return (<>
    <div className="p-6 flex justify-center">
      <input
        type="text"
        className="border p-2 border-slate-300 hover:border-b-indigo-900 focus:outline-none"
        placeholder='Buscar o crear nueva tarea'
        onChange={onSearchEvent}
      />
    </div>
    <span className="">{`Estas buscando: ${searchValue}`}</span>
  </>);
};

Comparto como quedo

import React from 'react';
import { TodoCounter} from './TodoCounter/TodoCounter';
import { TodoSearch } from './TodoSearch/TodoSearch';
import { CreateTodoButton } from './CreateTodoButton/CreateTodoButton';
import { TodoList } from './TodoList/TodoList';
import { TodoItem } from './TodoItem/TodoItem';


const todosList = [
{
  text: 'Learn React',
  completed: false
},
{
  text: 'Practice React',
  completed: false
},
{
  text: 'Some with React',
  completed: false
}
];
function App() {
  const [searchValue, setState] = React.useState('');
  
  const [todos, setTodos] = React.useState(todosList);
  const completedTodos = todos.filter(todo => todo.completed).length;
  const totalTodos = todos.length || todosList.length;


  const handleSearch = () => { return todos.filter(todo => todo.text.toLowerCase().includes(searchValue.toLowerCase())); };
  const todosFiltered = searchValue.length > 0 ? handleSearch() : todos;


  return (
    <React.Fragment>
          <TodoCounter todo={totalTodos} completed={completedTodos}></TodoCounter>
          <TodoSearch setState={setState} searchValue={searchValue}></TodoSearch>
          <CreateTodoButton></CreateTodoButton>
          <TodoList>
            { todosFiltered.map( todo => (<TodoItem key={todo.text} text={todo.text} completed={todo.completed}/> )) }
          </TodoList>
    </React.Fragment>
  );
}

export default App;

En mi versi贸n del app inclu铆 un filtro para saber cuales Todos est谩n pendientes y cu谩les completos. En c贸digo esto lo resolv铆 de la siguiente manera:

if(!searchValue.length >= 1){
    searchedTodos = (isChecked)
      ? todos.filter(todo => !!todo.completed)
      : todos.filter(todo => !todo.completed)
  }else{
    searchedTodos = todos.filter(todo => {
      return todo.text.toLowerCase().includes(searchValue.toLowerCase());
    })
  }

aqu铆 como lo hice 馃槂

Me exploto la cabeza esta clase!

sencillamente bien explicado el poder de react

  const filteredTodoList = todoList.filter((todo) => {
    const value = searchValue.trim().toLowerCase();
    const todoText = todo.text.trim().toLowerCase();

    if (value) {
      return todoText.includes(value) ? todo : undefined;
    }
    
    return todo;
  });

Tengo instalado el github copilot y me autogenero el c贸digo 馃槵馃槵

        {
          todos.map(todo=>
            {
              if(todo.text.toLowerCase().includes(searchValue.toLowerCase()))
                return <TodoItem key={todo.text} text={todo.text} completed={todo.completed}/>
            }
          )
        }

Esta es una forma de filtrar

Muy buena clase

Para solucionar el reto agregu茅 un m茅todo .filter al componente TodoList antes del .map

<TodoList className="TodoList">
        {
            todos.filter((todo) => {
              return todo.text.includes(searchValue)
            }).map((todo) => (
              <TodoItem
                className="TodoItem"
                key={todo.text}
                text={todo.text}
                completed={todo.completed}
              />
              ))
          }
</TodoList>

Primera vez que veo usar un filter de esa forma, ln28

Les comparto el searchedTodos con condicional ternaria

    let searchTodos = !searchValue.length >= 1 ?
        todos : todos.filter(todo => {
            const todoText = todo.text.toLowerCase()
            const searchText = searchValue.toLowerCase()
            return todoText.includes(searchText)
        })

Mi soluci贸n para filtrar los Todos dependiendo de las letras que escriban los usuarios en el input <TodosSearch/>

  1. Primero Definir donde se est谩n actualizando los caracteres ingresados por los usuarios:
    馃憠 Se encuentran en el estado searchValue

console.log(searchValue) //  Caracteres ingresados desde el input 
  1. Identificar donde se est谩n enviando los Todos:
    Estamos enviando todos los Todos
{todos.map((todo) => (
          <TodoItem
            key={todo.text}
            text={todo.text}
            completed={todo.completed}
          />
        )}
  1. Para filtrar los Todos dependiendo de los caracteres ingresados por los usuarios usamos el metodo .filte()r
    El cual crea un nuevo Array con los elementos que pases la condici贸n impuesta en la funci贸n:
  • Si no existen caracteres se mostraran todos los todos // return todo
  • Si nuestros Todos en su propierdad .text incluye caracteres ingresados desde input que identificamos gracias al estado searchValue. // Mostrar los Todos que incluyan los caracteres ingresados.

Usamos .toLowerCase() para filtrar sin importar que el usuario ingrese el texto en MAYUSCULAS o minusculas

todos.filter((todo) => {
          if (searchValue == "") {
            return todo
          } else if (todo.text.toLowerCase().includes(searchValue.toLowerCase())) {
            return todo
          }
        })
  1. Ahora s铆 usamos el metodo . map() crea un nuevo array con los resultados de la llamada a la funci贸n indicada aplicados a cada uno de sus elementos.
        {todos.filter((todo) => {
          if (searchValue == "") {
            //TODO: console.log(todo); // Array con todos los Todos y sus propiedades .text .completed
            //* console.log(todo.text); // No se retorna el Array filtado as铆=> todo.text porque el metodo .map lo renderiza en su propiedad ".text = todo.text"
            return todo
          } else if (todo.text.toLowerCase().includes(searchValue.toLowerCase())) {
            // console.log(searchValue.toLocaleLowerCase());
            return todo
          }
        }).map((todo) => (
          <TodoItem
            key={todo.text}
            text={todo.text}
            completed={todo.completed}
          />
        ))}

Resultado final 馃敟

Soluci贸n para el filtrado

import React, { useState } from 'react';
import { Fragment } from "react";
import TodoCounter from "./TodoCounter";
import TodoSearch from "./TodoSearch";
import TodoList from "./TodoList";
import TodoItems from './TodoItems';
import CreateTodoButton from "./CreateTodoButton";
import todosMock from '../mock/todosMock.json'

const App = () => {
  const [searchValue, setSearchValue] = useState('');
  const [todos, setTodos] = useState(todosMock);
  const completedTodos = todos.filter(todo => todo.completed).length;
  const totalTodos = todos.length;
  let todosFiltered = todos
  if (searchValue)
    todosFiltered = todosMock.filter(todo => todo.text.toLowerCase().includes(searchValue));
  return (
    <Fragment>
      <TodoCounter 
        total={totalTodos}
        completed={completedTodos}
      />
      <TodoSearch searchValue={searchValue} setSearchValue={setSearchValue} />
      <TodoList>
        <TodoItems todos={todosFiltered} setTodos={setTodos} />
      </TodoList>
      <CreateTodoButton />
    </Fragment>
  );
};

export default App;

Soluci贸n para eliminar y marcar como completado las tareas

import React from 'react';
import TodoItem from "../TodoItem";

const renderTodoItems = ({ todos, setTodos }) => todos.map((todo) => {

  const onComplete = (text, completed) => {
    alert(`You complete the todo ${text}`);
    const todoMapped = todos.map(todo => (todo.text === text ? {
      text,
      completed: !completed
    } : todo))
    setTodos(todoMapped);
  };

  const onDelete = (text) => {
    let newTodos = todos.filter(todo => todo.text !== text);
    setTodos(newTodos);
  };


  return (
    <TodoItem
      key={todo.text}
      text={todo.text}
      completed={todo.completed}
      onComplete={onComplete}
      onDelete={onDelete}
    />
  );
});

const TodoItems = (props) => renderTodoItems(props);

export default TodoItems;

Repo

TODOs Web Application

Para el reto cre茅 una lista de todos filtrados y simplemente hice el map con esa lista:

const todosFiltered = todos.filter(todo => todo.text.toLowerCase().includes(searchValue.toLowerCase()))

//entre los brackets de TodoList
{todosFiltered.map(todo => (
          <TodoItem 
          key={todo.text} 
          text={todo.text}
          completed={todo.completed} 
          />
        ))}

Este curso esta Genial 馃槂

const foundTodos = todos.filter(todo => (todo.text.toUpperCase()).includes(searchValue.toUpperCase()))

!! es la no false :v

Agregar un filtro de texto

const filtersTodos = todos.filter(todo => todo.text.startsWith(textSearched));

y pasar ese parametro a la lista:

<TodoList>
        {filtersTodos.map((todo, index) => (<TodoItem key={index} text={todo.text} completed={todo.completed}/>) )}
      </TodoList>

Here it is

<TodoList>
        {searchValue.length !== 0 ?  todos.filter(todo => todo.text.includes(searchValue)).map(todo => (<TodoItem text={todo.text} key={todo.text} completed={todo.compleated}/>)) :todos.map(todo => (
          <TodoItem text={todo.text} key={todo.text} completed={todo.compleated}/>
        ))}
      </TodoList>

Pienso que simplemente se puede utilizar la propiedad completed nada mas (sin el, !!), ya que esta es un booleano por lo tanto se contaran los true:

const completedTodos = todos.filter(todo => todo.completed).length;
import React from 'react';

import './TodoSearch.css';
function TodoSearch({state1,setState1}){
	
  const onSearchValueChange = (event) => {
    console.log(event.target.value);
    setState1(event.target.value.toLowerCase())
  };
  
  return (
    <React.Fragment>
    <input
      className="TodoSearch"
      placeholder="Cebolla"
      onChange={onSearchValueChange}
      value={state1}
      />
     <p>
      {state1}
       </p>
       </React.Fragment>
  );;
}

export {TodoSearch};

//import './App.css';

import React from "react";
import {TodoCounter} from "./component/TodoCounter";
import {TodoItem} from "./component/TodoItem";
import {TodoList} from "./component/TodoList";
import {TodoSearch} from "./component/TodoSearch";
import {NewTodo} from "./component/NewTodo";

const todos =[
  {text: 'cc',completed:false},
  {text: 'cc1',completed:false},
  {text: 'cc2',completed:true},
  {text: 'cc3',completed:false},
  {text: 'cc4',completed:false},
  {text: 'cc5',completed:true},
]

function App() {
  const [stateTodos,setStateTodos] = React.useState(todos)
  const [searchState,setSearchState1] = React.useState('')
  return (
    <React.Fragment>
      <TodoCounter stateTodos={stateTodos} />
      <TodoSearch state1={searchState} setState1={setSearchState1}/>
        <TodoList>
          {stateTodos.filter(todo => searchState == ""?true:todo.text.toLowerCase().includes(searchState) ).map((todo,key)=><TodoItem key={key} text={todo.text} completed={todo.completed} setStasetStateTodos= {setStateTodos}teTodos= {setStateTodos}></TodoItem>)}
        </TodoList>
        <NewTodo stateTodos ={stateTodos} setStateTodos= {setStateTodos} />
    </React.Fragment>
  );
}

export default App;

Yo hice diferente la funci贸n de borrar, usando filter, la dejo esperando a que a alguien le sirva.

const deleteTodo = ( text ) => {
    const newTodos = todos.filter( todo => todo.text !== text );
    setTodos(newTodos);
  };

Mi soluci贸n de los dos retos:

1. Search:

  • En caso de que no hayamos escrito nada se seguir谩n mostrando todos los Todos del arreglo original porque el m茅todo includes devuelve true cuando le pasamos un string vac铆o
const filteredTodos = todos.filter((todos) => {
    return todos.text.toLowerCase().includes(searchValue.toLowerCase());
  });

<TodoList>
        {filteredTodos.map((todo, i) => (
          <TodoItem
            key={i}
            text={todo.text}
            completed={todo.isCompleted}
          />
        ))}
      </TodoList>

2. Add y Delete:

  • Para el segundo reto tuve que pasar el estado todos y setTodos del componente App al componente TodoItem en los props para modificarlo directamente en la funci贸n onComplete y onDelete.
 const onComplete = () => {
    const newTodos = [...todos];
    newTodos[pos].isCompleted = !newTodos[pos].isCompleted;
    setTodos(newTodos);
  };

  const onDelete = () => {
    const newTodos = [...todos].filter((todo) => todo.text !== text);
    console.log(newTodos);
    setTodos(newTodos);
  };
Creo que el Sql quedo obsoleto xD

Okey鈥 Tendre que ver este curso como 3 veces

Lo dijoooo!!! lo dijooooo!!!