React
Installation & Setup
In your project, add the @abc-editor/react
package and the abcjs
rendering library as dependencies:
If you’re using the editor with the built-in toolbar, you’ll also need the CSS file located at /dist/style.css
within the @abc-editor/react
package. How to include the CSS file depends on the build tool that you’re using. If you’re using a bundler like Vite or Parcel, you can just import the CSS file:
Basic Editor
This shows a basic setup of the interactive notation editor, using the ABCEditor
component with the built-in toolbar. We can use the component’s onChange
handler to update the ABC notation in the text field below, as the user writes their melody. Keyboard shortcuts are also enabled in the editor props.
Generated ABC notation:
Code
import { useState } from "react";
import { ABCEditor } from "@abc-editor/react";
import "@abc-editor/react/dist/style.css";
export default function ReactBasicEditor() {
const [abc, setAbc] = useState("");
return (
<div>
<ABCEditor responsive enableKbdShortcuts onChange={setAbc} />
<br />
<p>Generated ABC notation:</p>
<textarea readOnly rows={6} cols={50} value={abc} />
</div>
);
}
Exercise
This demonstrates how to setup a simple exercise/game using the notation editor. When the user successfully enters the notes of a one-octave G Major scale, the notes turn green and celebrations ensue. Notice we are making use of one of the handy CSS classes from the abcjs rendering library, in order to select the note elements. Also notice we need to wrap the onChange
callback in a useCallback
hook in order to avoid infinite re-renders.
Write a G Major scale using quarter notes, starting from G above middle C:
Code
import { useCallback } from "react";
import Confetti from "js-confetti";
import { ABCEditor, type ABCEditorChangeHandler } from "@abc-editor/react";
import "@abc-editor/react/dist/style.css";
const GMajorScaleAbc = "G2 A2 B2 c2 | d2 e2 ^f2 g2";
export default function ReactExercise() {
const onChange: ABCEditorChangeHandler = useCallback((abc, _, renderDiv) => {
if (abc.includes(GMajorScaleAbc)) {
renderDiv
?.querySelectorAll(".abcjs-note")
.forEach((note) => note.setAttribute("fill", "#10bb26"));
new Confetti().addConfetti();
}
}, []);
return (
<div>
<ABCEditor
responsive
ending={{ lastMeasure: 2 }}
lineBreaks={[2]}
onChange={onChange}
/>
</div>
);
}