简体   繁体   English

反应从孩子到父母的更新数组道具

[英]React update array prop from child to parent

Hello I am struggling to properly update my state from my child component to my parent.您好,我正在努力将我的 state 从我的子组件正确更新到我的父组件。 Basically I am trying to set the current state to true onclick.基本上我正在尝试将当前的 state 设置为真正的 onclick。

This is my parent component:这是我的父组件:

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} />

This is my child Component (Sidebar)这是我的子组件(侧边栏)

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)}

There are three problems:存在三个问题:

  1. You never call setNavigation with your new array.你永远不会用你的新数组调用setNavigation

  2. You don't clear current on the formerly-current item.您没有清除以前current项目的当前项目。

  3. Although you're creating a new array, you're reusing the objects within it, even when you change them, which is against the Do Not Modify State Directly rule.虽然您正在创建一个新数组,但您正在重用其中的对象,即使您更改它们也是如此,这违反了Do Not Modify State Directly规则。

To fix all three (see *** comments):修复所有三个(见***评论):

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);
};

Separately, though, I would suggest separating navigation out into two things:不过,另外,我建议将navigation分为两件事:

  • The set of navigation objects.导航对象集。
  • The name of the current navigation item.当前导航项的名称。

Then setting the navigation item is just setting a new string, not creating a whole new array with an updated object in it.然后设置导航项只是设置一个新字符串,而不是创建一个包含更新的 object 的全新数组。

TJ Crowder's solution and explanation are great . TJ Crowder 的解决方案和解释很棒 Additionally, you can write that logic in a shorter syntax.此外,您可以用更短的语法编写该逻辑。 Just a preference.只是一种偏好。

const newNavigation = navigation.map(nav => {
  return nav.name === name 
    ? { ...nav, current: true } 
    : { ...nav, current: false }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM