Estoy codificando una aplicación de reacción en la que un usuario puede hacer clic en un botón para intercambiar un elemento en una matriz con el elemento a su izquierda. Escribí una función para implementar esto sin mutar la matriz de elementos original que se muestra en la página, pero esta función no le hace nada a mi código ni devuelve ningún error.
Aquí está el componente de mi aplicación, que define la función swapLeft y luego pasa esa función al componente Item como accesorios:
import React, { useState } from "react"; import Form from "./components/Form"; import Item from "./components/Item"; import { nanoid } from "nanoid"; import './App.css'; function App(props) { const [items, setItems] = useState(props.items); function deleteItem(id) { const remainingItems = items.filter(item => id !== item.id); setItems(remainingItems); } function swapLeft(index) { const index2 = index - 1; const newItems = items.slice(); newItems[index] = items[index2]; newItems[index2] = items[index]; return newItems; } const itemList = items .map((item, index) => ( <Item id={item.id} index={index} name={item.name} key={item.id} deleteItem={deleteItem} swapLeft={swapLeft} /> )); function addItem(name) { const newItem = { id: "item-" + nanoid(), name: name }; setItems([...items, newItem]); } return ( <div className="form"> <Form addItem={addItem} /> <ul className="names"> {itemList} </ul> </div> ); } export default App;
Y el componente Item:
import React from "react"; import { Button, Card, CardContent, CardHeader } from 'semantic-ui-react' export default function Item(props) { return ( <Card> <CardContent> <CardHeader> {props.name}</CardHeader> <Button onClick={() => props.deleteItem(props.id)}> Delete <span className="visually-hidden"> {props.name}</span> </Button> </CardContent> <CardContent style={{ display: 'flex' }}> <i className="arrow left icon" onClick={() => props.swapLeft(props.index)} style={{ color: 'blue'}}></i> <i className="arrow right icon" style={{ color: 'blue'}}></i> </CardContent> </Card> ); }
¿Hay una mejor manera de escribir esta función e implementarla? Supongo que podría hacer algo con el gancho React setState, pero esta parecía una solución más fácil. Soy nuevo en React, por lo que cualquier información sería útil.
La forma en que React sabe si el estado ha cambiado es si el estado se refiere a una dirección completamente diferente en la memoria. En el caso de las matrices, si desea que React vuelva a representar la página porque la matriz en el estado cambió, debe proporcionarle una matriz completamente nueva . La modificación de la matriz existente no activará el proceso de renderizado.
Básicamente, lo que debe hacer es cambiar la última línea de la función swapLeft
a
setItems(newItems)
Si desea que los cambios surtan efecto de inmediato (que es lo que supongo que desea hacer aquí)
También puede usar el valor de retorno de la función y cambiar el estado en otro componente, FYI.
EDITAR:
Miré esto nuevamente, y su implementación de intercambio también es incorrecta, pero incluso si lo corrigió, aún no vería un cambio, a menos que hiciera lo que mencioné anteriormente
La función completa correcta sería
function swapLeft(index) { const index2 = index - 1; const newItems = items.slice(); const temp = items[index]; newItems[index] = items[index2]; newItems[index2] = temp; setItems(newItems); }
Solo para quizás aclarar el anterior. Si no llama a setState, su componente no se vuelve a representar. Esto significa que no importa lo que haga con esas matrices, no será visible en la pantalla.