Hola, tengo dificultades para actualizar correctamente mi estado de mi componente secundario a mi componente principal. Básicamente, estoy tratando de establecer el estado actual en true onclick.
Este es mi componente principal:
export default function Layout({ children }: Props) { const [navigation, setNavigation] = useState([ { name: 'Dashboard', href: '/', icon: HomeIcon, current: true }, { name: 'Create Fact', href: '/facts/create', icon: UsersIcon, current: false }, { name: 'Documents', href: '/documents', icon: InboxIcon, current: false } ]) return ( <> <Sidebar navigation={navigation} setNavigation={setNavigation} />Este es mi componente secundario (barra lateral)
type Props = { navigation: Array<{ name: string href: string icon: any current: boolean }> setNavigation: ( navigation: Array<{ name: string href: string icon: any current: boolean }> ) => void } const Sidebar = ({navigation, setNavigation}: Props) => { const router = useRouter() const toggleNavigation = (name: string) => { // todo: Here I would like to properly update the state with the current selected navigation item (current) const newNavigation = navigation.map(nav => { if (nav.name === name) { nav.current = true return nav } }) } return ( <nav className="flex-1 px-2 pb-4 space-y-1"> {navigation.map(item => ( <span onClick={() => toggleNavigation(item.name)}Hay tres problemas:
Nunca llamas a setNavigation con tu nueva matriz.
No borra el elemento current en el elemento anteriormente actual.
Aunque está creando una nueva matriz, está reutilizando los objetos que contiene, incluso cuando los cambia, lo que va en contra de la regla No modificar el estado directamente .
Para arreglar los tres (ver *** comentarios):
const toggleNavigation = (name: string) => { const newNavigation = navigation.map(nav => { if (nav.name === name) { // *** #3 Create a *new* object with the updated state nav = {...nav, current: true}; } else if (nav.current) { // *** #2 make the old current no longer current nav = {...nav, current: false}; } return nav; }); // *** #1 Do the call to set the navigation setNavigation(newNavigation); }; Sin embargo, por separado, sugeriría separar la navigation en dos cosas:
Luego, configurar el elemento de navegación es simplemente configurar una nueva cadena, no crear una matriz completamente nueva con un objeto actualizado.
La solución y la explicación de TJ Crowder son geniales . Además, puede escribir esa lógica en una sintaxis más corta. Solo una preferencia.
const newNavigation = navigation.map(nav => { return nav.name === name ? { ...nav, current: true } : { ...nav, current: false } })