Estoy tratando de crear una aplicación de rompecabezas simple para mi proyecto de reacción personal.
Básicamente, hice una matriz con objetos y mapeé a través de esta matriz para generar listas de rompecabezas.
const puzzleData = [ { id: Math.random() * 5, value: '<main>', key: 'main' }, { id: Math.random() * 5, value: '</main>', key: 'main' }, { id: Math.random() * 5, value: '<section>', key: 'section' }, { id: Math.random() * 5, value: '</section>', key: 'section' }, { id: Math.random() * 5, value: '<nav>', key: 'nav' }, { id: Math.random() * 5, value: '</nav>', key: 'nav' }, { id: Math.random() * 5, value: '<footer>', key: 'footer' }, { id: Math.random() * 5, value: '</footer>', key: 'footer' }, { id: Math.random() * 5, value: '<aside>', key: 'aside' }, { id: Math.random() * 5, value: '</aside>', key: 'aside' }, { id: Math.random() * 5, value: '<h1>', key: 'h1' }, { id: Math.random() * 5, value: '</h1>', key: 'h1' }, { id: Math.random() * 5, value: '<p>', key: 'p' }, { id: Math.random() * 5, value: '</p>', key: 'p' }, { id: Math.random() * 5, value: '<span>', key: 'span' }, { id: Math.random() * 5, value: '</span>', key: 'span' }, ]; const [puzzle, setPuzzle] = useState([...puzzleData]); <ul className={styles.puzzle}> {puzzle.map((item, i) => { return ( <li key={item.id} onClick={() => { filterHandler(item.key, item.id); }} style={{ backgroundColor: color.id === item.id ? 'white' : null }} > {item.value} </li> ); })} </ul>
Quiero que se aplique mi función filterHandler onClick para filtrar la matriz de rompecabezas cuando el usuario hace clic en los mismos elementos li con el mismo valor clave. Por ejemplo, cuando el usuario hace clic en principal y /principal en elementos li, filtre la matriz de rompecabezas para eliminar esos dos de los elementos representados. A continuación se muestra mi función filterHandler actual.
const filterHandler = (key, id) => { setPuzzle((prevState) => { const updated = prevState.filter( (item) => item.key !== key || item.id !== id ); return updated; });
En este momento, está filtrando el elemento li en el que hace clic el usuario, pero quiero filtrar el elemento li cuando el usuario hace clic en dos elementos iguales con los mismos valores clave (como un juego de rompecabezas real). ¿Hay alguna manera de aplicar esta lógica con el método de filtro? ¡Gracias por adelantado!
Tendrá que mantener una variable de estado para realizar un seguimiento de en qué elemento ha hecho clic el usuario antes de permitir que el usuario haga el segundo clic. De esa manera, tendrá almacenado el elemento en el que se hizo clic anteriormente, que podrá comparar con el segundo clic del usuario en el elemento.
const [lastElementClick, setLastElementClick] = useState("")
Ahora, dentro de su función filterHandler()
, podemos verificar en cualquier momento si el último elemento en el que se hizo clic coincide con nuestra clave actual. También eliminé la segunda condición dentro de su condición de filter
(esto era necesario para eliminar ambos elementos, de lo contrario, solo se eliminará el último elemento en el que se hizo clic)
const filterHandler = (key, id) => { if(lastElementClick === key) { setPuzzle((prevState) => { const updated = prevState.filter( (item) => item.key !== key ); return updated; }); setLastElementClick(key) } else { setLastElementClick(key) } };
ACTUALIZACIÓN: para evitar la eliminación del bloque al hacer clic dos veces en el mismo elemento, debemos agregar otra verificación en nuestra condición if. Ya estamos haciendo coincidir si lastElement coincide con nuestra clave actual, ahora podemos agregar una condición para asegurarnos de que la identificación de id
no coincida con la id
actual (es decir, no se hace clic en el mismo elemento)
Por esta razón, actualizaré la variable de estado para que contenga tanto la clave como la identificación del último elemento en el que se hizo clic.
const [lastElementClick, setLastElementClick] = useState({ id: "", key: "" });
Después de eso, podemos actualizar la condición if al verificar también la identificación:
const filterHandler = (key, id) => { if (lastElementClick.key === key && lastElementClick.id !== id) { const updated = puzzle.filter((item) => item.key !== key); setPuzzle(updated); setLastElementClick({ key, id }); } else { setLastElementClick({ key, id }); } };
También actualicé el código en el siguiente enlace, también puedes probarlo,
Aquí hay un enlace al código de trabajo completo: https://codesandbox.io/s/modest-williams-lun0f?file=/src/App.js:1223-1539