【问题标题】:State change not reflecting on child component in react状态变化不反映反应中的子组件
【发布时间】:2020-07-20 17:37:54
【问题描述】:

我有两个子组件更新父组件的相同状态。两个子组件都包含一个循环,循环的每个元素都会在点击事件时更新状态。

父组件:-

const [selected, setSelected] = useState('')

const selectContact = (e: SyntheticEvent<HTMLDivElement>) => {
    const {id} = e.currentTarget
    setSelected(id)
    console.log(id)
}


<ChannelList selected={selected} setSelected={selectContact}
          ....other props />

<FriendList selected={selected} setSelected={selectContact} ......other props />}

我显然没有包含整个组件。

ChannelList 组件:-

{channels.map(channel =>
    <div key={channel.id}>
        <div id={channel.id}
             className={`channel-list ${selected === channel.id && 'selected-channel'}`}
             onClick={(e) => {
                  setSelected(e)
                  channelDetails(channel.id)
             }}

        // .....rest of my code
    <div>
}

FriendList 组件:-

{friends.map(friend =>
     <div key={friend.id} id={friend.id}
          className={`friend-list-item ${selected === friend.id && 'selected-user'}`}
          onClick={(e) => setSelected(e)}>

     //.......the rest
     <div>
}

我想做的是根据状态改变样式。如果我单击同一组件中的不同项目,则状态会更新并且 CSS 会正常呈现。但是,如果我单击另一个组件上的任何内容,尽管状态会更新,但 CSS 样式会保留在两个组件上。

this is the what happens that i don't want

我想要的是样式应该只呈现在其中一个组件上。 我正在使用 react hooks 和 Typescript。

换句话说,如果我点击一个朋友的名字,选择的频道应该被取消选择,反之亦然。

任何帮助将不胜感激。

【问题讨论】:

  • 嘿,@Ashki80。是否可以创建codesandbox
  • 我会试试的。但是想象一下。父组件已获得状态。当子 B 更新状态时,虽然子 B 更新,但子 A 不更新(反之亦然)

标签: reactjs


【解决方案1】:

您是否尝试过使用 Mobx 或 Redux 等任何状态管理库来观察变化?我认为使用其中之一应该可以解决您的问题。

【讨论】:

  • 我使用了 mobx 商店,它解决了这个问题,但假设项目很小。我不想仅仅为了一个小问题而安装整个库。感谢您的帮助
【解决方案2】:

您在两个组件上与相同的 id 发生冲突。我可以建议一些方法:

一,您可以使用前缀来定义您选择的状态:

const selectContact = (prefix: String) => (e: SyntheticEvent<HTMLDivElement>) => {
    const {id} = e.currentTarget
    setSelected(`${prefix}_${id}`)
}

<ChannelList selected={selected} setSelected={() => selectContact('channel')}
      ....other props />
<FriendList selected={selected} setSelected={() => selectContact('friend')} ......other props />

在频道和好友组件中,您还可以验证前缀:

{channels.map(channel =>
    <div key={channel.id}>
        <div id={channel.id}
             className={`channel-list ${selected === `channel_${channel.id}` && 'selected-channel'}`}
             onClick={(e) => {
                  setSelected(e)
                  channelDetails(channel.id)
             }}

        // .....rest of my code
    <div>
}

另外,你可以创建另一个状态来控制选择哪个组件(这与前缀几乎相同):

const [selected, setSelected] = useState('')
const [componentName, setComponentName] = useState('')
const selectContact = (componentName: String) => (e: SyntheticEvent<HTMLDivElement>) => {
    const {id} = e.currentTarget
    setComponentName(componentName)
    setSelected(id)
}
 <ChannelList selected={selected} isComponentSelected={componentName === 'channel'} setSelected={() => selectContact('channel')}
      ....other props />
<FriendList selected={selected} isComponentSelected={componentName === 'friend'} setSelected={() => selectContact('friend')} ......other props />

在频道:

{channels.map(channel =>
    <div key={channel.id}>
        <div id={channel.id}
             className={`channel-list ${isComponentSelected && selected === channel.id && 'selected-channel'}`}
             onClick={(e) => {
                  setSelected(e)
                  channelDetails(channel.id)
             }}

        // .....rest of my code
    <div>
}

【讨论】:

  • 感谢您的回答。但是 id 很少有发生冲突的机会。它们是从后端生成的指南。我什至安慰了他们。不过,传递前缀是个好主意。
猜你喜欢
  • 2019-10-15
  • 1970-01-01
  • 2021-05-21
  • 1970-01-01
  • 2019-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
相关资源
最近更新 更多