【问题标题】:When I set state via useState in parent component, my props in the child I'm passing down to are undefined当我在父组件中通过 useState 设置状态时,我传递给的孩子中的道具是未定义的
【发布时间】:2019-12-16 05:09:32
【问题描述】:

我有一个父组件 Listings,它有一个来自种子文件的对象数组。我只想在页面加载时加载 14 个对象中的前 9 个。

const Listings = () => {
  const [ listingsData, setListings] = useState(listings);

  const [ homesDisplayed , setDisplayNumber ] = useState(listingsData.slice(0, 9));
  const homes = homesDisplayed.map((home, index) => (
    <div className="col xl4" key={index}>
      <HomeListingCard 
        name={home.homeName}
        imageUrl={home.imageURL}
        beds={home.beds}
        baths={home.baths}
        isMultiSection={home.isMultiSection}
        sqft={home.sqft}
        startingPrice={home.startingPrice}
      />
    </div>
  ));

  return (
    <div>
      <div className="row">
        <div className="listings-subheader">
          <h3 className="left available-homes">{`${listingsData.length} `}homes available</h3>
          <div className="right">
            <SortBy />
          </div>
        </div>
      </div>
      <div className="row">
        {homes}
      </div>
      <div className="row">
        <LoadListings listings={listingsData} homesDisplayed={homes} setDisplayNumber={setDisplayNumber} />
      </div>
    </div>
  )
}

export default Listings;

我使用const [ homesDisplayed , setDisplayNumber ] = useState(listingsData.slice(0, 9)); 将一个包含 9 个对象的数组设置为状态。

这很好用。

然后我试图将我的状态作为道具传递给子组件,如下所示:

<LoadListings listings={listingsData} homesDisplayed={homes} setDisplayNumber={setDisplayNumber} />

当页面最初加载时,这些道具有数据。但是当我点击&lt;LoadListings /&gt;子组件中的一个按钮到console.log(props)时,我的数据都是未定义的。

&lt;LoadListings /&gt; 看起来像:

const LoadListings = (props) => {
    const updateListings = (props) => {
        console.log(props.homes);
        // props.setDisplayNumber(...props.homesDisplayed, props.listings.slice(9, 12));
    }

    return (
        <button onClick={updateListings}>Load More</button>
    )
}

我的目标是单击按钮,然后将 updateLIstings 从原来的 14 数组中再拼接 3 个,然后像这样将它们添加到 homeDisplayed 数组中

const updateListings = (props) => {
        props.setDisplayNumber(...props.homesDisplayed, props.listings.slice(9, 12));
}

但是 props.homesDisplayed - 以及所有的 props - 都是未定义的。

谢谢。

【问题讨论】:

  • 从哪里传递 useState(listings) 中的列表?
  • 在 我正在从种子文件中导入一个数组。 '从'./seed.js'导入列表;'
  • 当我在加载页面后查看反应开发人员工具时,道具存在于我的子组件中。但是然后我单击带有附加功能的按钮,那里什么都没有。
  • 您正在发送从onClick 回调调用它的事件props。此事件没有homes 属性,因此它返回未定义。我认为您不想传递任何论点:const updateListings = () =&gt; {

标签: reactjs react-hooks react-state-management react-state


【解决方案1】:

发生这种情况是因为您实际上没有将 props 传递给 updateListings 函数。

如果您仔细查看您的函数声明,您会注意到您已将props 定义为参数。然后,在 onClick 属性上,您实际上并没有向函数传递任何内容到。

想想updateListings 函数的作用域...你实际上不需要传递任何东西,因为它已经可以从父作用域访问props。不幸的是,通过将 props 第二次定义为函数参数,您将遮蔽更高范围的 props(实际上是告诉函数忽略它)。

如果您更新 updateListings 以省略 props 参数,它应该工作(除非您的代码中出现任何其他问题)。

const updateListings = (props) => {
  console.log(props.homes);
  props.setDisplayNumber(...props.homesDisplayed, props.listings.slice(9, 12));
}

旁注:您可能只想存储要显示的项目数量,而不是将切片数据存储在状态中。这样,您可以通过在渲染本身中执行切片来简化一切,而不是推理状态中的数据。例如:

const [ listingsData, setListings] = useState(listings);

// Store number to display
const [ homesDisplayed , setDisplayNumber ] = useState(9);

// Slice before map, which'll update every time you increment `homesDisplayed
const homes = homesDisplayed.slice(0, homesDisplayed).map((home, index) => (
  <div className="col xl4" key={index}>
    <HomeListingCard 
      name={home.homeName}
      imageUrl={home.imageURL}
      beds={home.beds}
      baths={home.baths}
      isMultiSection={home.isMultiSection}
      sqft={home.sqft}
      startingPrice={home.startingPrice}
    />
  </div>
));

另一个注意事项:通常,您需要始终按照varName, setVarName 的约定命名您的[state, setState] val/updater。这样一来,当您尝试协调什么控制什么时,读者(和您!)就不会感到困惑。

所以我建议将[homesDisplayed, setDisplayNumber] 更改为[displayNumber, setDisplayNumber]。

【讨论】:

  • 非常感谢。你关于状态的建议只跟踪数字而不是数据有很大帮助。对此,我真的非常感激。你教会了我很多东西。
猜你喜欢
  • 2023-03-15
  • 2020-08-06
  • 2017-02-19
  • 2017-06-03
  • 1970-01-01
  • 2021-10-05
  • 2017-08-22
  • 2019-04-17
  • 2022-11-05
相关资源
最近更新 更多