我正在构建几个组件,并且遇到了一些绊脚石。
这些组件从钢琴键盘开始,我可以在钢琴键盘上叠加不同的音乐实体,例如音符,音程,和弦,音阶等,方法是通过notes={[]}
数组道具将音符名称传递到{{ 1}}组件。然后,在该组件的特定实例中,将其导入到Keyboard
组件中,在其中添加了音阶和音符按钮,因此可以在此实例的整个音阶上覆盖整个键盘,这基本上可以正常工作。有一个音符名称列表,我可以单击该音符名称,然后将该音阶覆盖在键盘上方,如下所示:
The gif shows the current behavior of the Scales
component, which is not quite correct yet...
在gif中,您可以看到主要和次要音阶按钮更改了音阶的状态,然后音符名称按钮使用该音阶来更改其下方键盘的状态。但是我还希望它做的是单击主按钮或次按钮时切换当前选择的音阶,但是当前音符名称按钮不会自动响应主按钮和次按钮的状态变化,但是必须再次单击以进行更改。
我想要的是能够仅单击大调和小调按钮,并且无论选择哪个音符,都将简单地从大调更改为小调,而不必再次单击所选的音阶音符,这是当前的行为。 / p>
因此,在我的Scales组件中,我使用了像这样的自定义单选按钮,首先要控制主要和次要按钮:
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>
...并且通过两个useState挂钩建立状态,如下所示:
<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>
...然后,最终导入的const [ scale, setScale] = useState('')
const [ notes, setNotes] = useState([])
组件从注释按钮中接收到Keyboard
道具,就像这样:
notes={notes}
...所以我真的不知道如何知道音符按钮或知道所单击的缩放按钮,然后将该信息转换为键盘<Keyboard octaves={'2'} notes={notes}/>
道具,这就是我所在的位置现在卡住了...
这是组件的代码沙箱:
https://codesandbox.io/s/scales-981uk
谢谢您的帮助:-)
答案 0 :(得分:0)
我查看了您的代码。
您现在遇到的问题是,单击主按钮时,笔记组件未重新渲染和重新设置样式。在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>