如何使选定的单选按钮根据另一个单选按钮更改另一个状态来更改一个状态?

Posted

技术标签:

【中文标题】如何使选定的单选按钮根据另一个单选按钮更改另一个状态来更改一个状态?【英文标题】:How do I make a selected radio button change one piece of state based upon another radio button changing another piece of state? 【发布时间】:2020-05-29 23:19:54 【问题描述】:

我正在构建几个组件,但遇到了一些绊脚石。

组件以钢琴键盘开始,我可以在其上叠加不同的音乐实体,如音符、音程、和弦、音阶等...通过将音符名称通过 notes=[] 数组道具传递到 Keyboard 组件.然后在组件的这个特定实例中,我将它导入到Scales 组件中,我在其中添加了比例和注释按钮,因此我可以在此实例中将整个比例覆盖在键盘顶部,这基本上都可以工作。有一个我可以单击的音符名称列表,然后将其覆盖在键盘顶部,如下所示:

The gif shows the current behavior of the Scales component, which is not quite correct yet...

在 gif 中,您可以看到大调和小调音阶按钮改变了音阶的状态,然后音符名称按钮使用它来改变其下方键盘的状态。但我还希望它做的是在单击主要或次要按钮时切换当前选择的音阶,但目前音符名称按钮不会自动对主要和次要按钮的状态变化做出反应,但必须再次单击以进行更改。

我想要的是能够只单击大调和小调按钮,并且选择的任何一个音符都会简单地从大调变为小调,而无需再次重新单击选定的音阶音符,这是当前的行为。

所以,在我的 Scales 组件中,我使用了自定义单选按钮,首先是控制主要和次要按钮:

<MajorInput
  type="radio"
  name="scale"
  id="major"
  label="major"
  value="major"
  checked=scale === 'major'
  onChange=handleChange
  onClick=() => setScale('major')
/>
<MajorLabel
  whileHover= scale: 1 
  whileTap= scale: 0.9 
  htmlFor="major"
>
  Major
</MajorLabel>

...然后控制笔记按钮,如下所示:

<NoteInput
  id="c"
  scale=scale
  type="radio"
  name="notes"
  label="c"
  value="c"
  onClick=
    () => setNotes(
      scale === 'major' ? ['c1p', 'd1ma', 'e1ma', 'f1p', 'g1p', 'a1ma', 'b1ma'] :
      scale === 'minor' ? ['c1p', 'd1ma', 'eb1mi', 'f1p', 'g1p', 'ab1mi', 'bb1mi'] :
      ''
    )
  
/>
<NoteLabel
  whileHover= scale: 1 
  whileTap= scale: 0.9 
  scale=scale
  htmlFor="c"
>

  scale === 'major' ? 'C' :
  scale === 'minor' ? 'C' :
  'C'

</NoteLabel>

...状态是通过两个 useState 钩子建立的,如下所示:

const [ scale, setScale] = useState('')

const [ notes, setNotes] = useState([])

...然后最终导入的Keyboard 组件从注释按钮接收它的notes=notes 属性,如下所示:

<Keyboard octaves='2' notes=notes/>

...所以我真的不知道如何让注释按钮知道或知道被单击的比例按钮,然后将该信息转换为键盘 notes 道具,这就是我现在卡住的地方...

这里是组件的代码沙箱:

https://codesandbox.io/s/scales-981uk

感谢您的帮助:-)

【问题讨论】:

您可以使用redux 之类的状态管理工具,用于组件之间的复杂数据流,满足现在和未来的需求。 【参考方案1】:

我查看了您的代码。

您现在遇到的问题是,当单击主要按钮时,您的笔记组件没有重新呈现和重新设置样式。在 React 中,您可以使用 props 的更改来触发重新渲染,这也会重新设置您的笔记样式。

我建议将您所有的笔记输入放入一个子组件中。 :

// ./Scales.js

import NoteButtonBox from ./NoteButtonBox.js

//...

// important: pass scale as props. 
// Everytime scale changes, the note buttons are rerendered and restyled
sub component
  return (
    <Container>
      <ScaleButtonBox>
        /* ... */
      <ScaleButtonBox>
      <NoteButtonBox scale=scale />
      /* ... */
// ./NoteButtonBox.js


const NoteButtonBox = (scale) => 
   // Don't forget to also move 'const [notes, setNotes] = useState([]);' into the 
  const [notes, setNotes] = useState([]);
  return  
    /* return your styled notes based on props scale */
  


编辑

对于需要跨多个子组件访问状态的情况,可以使用React Context。或者,您可以使用 React Redux 来完成同样的事情。我建议使用 Comtext,因为它是 React 的原生部分。

将您的应用程序分解为子组件似乎是不必要的工作,但在 React 中创建许多小组件是一种很好的做法。 React 鼓励像我建议的那样组合。

    创建一个NotesStateContext 类。 您定义需要它的位置NotesStateContext.Provider
      <NotesStateContext.Provider value="dark">
        <NoteButtonBox />
        </* All other components that need to access the state of your notes */>
      </NotesStateContext.Provider>
    从提供者获取和更新您的状态

【讨论】:

hmmmm...使用这种方法遇到了一个新问题,因为我将 notes=notes 传递到 Scales 组件底部的键盘组件中,如下所示:jsx &lt;Keyboard octaves="2" notes=notes /&gt;,但由于我将笔记状态移动到一个单独的组件中我不确定如何将notes 状态输入键盘,这就是它如何知道要更改哪些笔记以及如何... hmmmm...我意识到了一些事情...当我点击所有笔记按钮中的比例按钮时,比例的状态正在更新,但这不会自动制作笔记按钮更新便笺状态...所以现在我在想问题可能是我需要便笺按钮自动更新便笺状态,但前提是当前选择了便笺按钮... ...所以当我使用比例按钮切换比例然后点击当前选择的比例按钮时,它确实会更新以显示正确的比例,但只有在我点击比例按钮之后。 ..所以现在我在想问题可能是我需要注释按钮来自动更新注释状态,但前提是当前选择了特定的注释按钮... 是的,在 React 中,每个状态更新都会触发重新渲染,然后应该重新设置您的笔记样式。 好的,我会试着在上下文中思考一下,看看我是否可以让它工作......不过,这需要我一些时间,但希望它可以工作 XD

以上是关于如何使选定的单选按钮根据另一个单选按钮更改另一个状态来更改一个状态?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过检查另一个单选按钮来设置选中的单选按钮

更改单选按钮选中状态时如何从单选按钮组中的单选按钮获取文本

基于选定的单选按钮在 Tkinter 中启动命令?

如何以编程方式更改表格单元格中单选按钮组的单选按钮?

改进单选按钮的使用以启用/禁用表单字段

仅从选定的单选按钮选项提交表单数据