So I am using the Context API from React and have one component called CreateComposition
that uses the createContext()
and exports it. I then import it into a component called Compositions
, and use useContext()
to display it as a list. However when I go between the two, they do not save.
This is the current code I have for both components.
import React, { useState, createContext } from 'react';
import { Link } from 'react-router-dom';
const CompositionsContext = createContext([' No Compositions Currently']);
const CreateComposition = () => {
const [taal, setTaal] = useState('');
const [bpm, setBpm] = useState('');
const [name, setName] = useState('');
const [compositions, setCompositions] = useState([]);
const sayKayeda = () => {
alert(taal + " " + bpm + " " + name);
}
const changeTaal = (event) => {
setTaal(event.target.value);
}
const changeBPM = (event) => {
setBpm(event.target.value);
}
const changeName = (event) => {
setName(event.target.value);
}
const addNewComposition = () => {
const newComposition = `${taal} ${bpm} ${name}`;
setCompositions([...compositions, newComposition]);
setTaal('');
setBpm('');
setName('');
}
return (
<CompositionsContext.Provider value={compositions}>
<h2>Input Kayeda Details Below</h2>
<br></br>
<br></br>
<label><b>Taal</b>
<input onChange={changeTaal} value={taal}></input>
</label>
<br></br>
<label><b>BPM</b>
<input onChange={changeBPM} value={bpm}></input>
</label>
<br></br>
<label><b>Name</b>
<input onChange={changeName} value={name}></input>
</label>
<p></p>
<button onClick={sayKayeda}>Current Kayeda</button>
<button onClick={addNewComposition}>Add Composition</button>
<br></br>
<Link to='/compositions' className='btn'><h2>Compositions</h2></Link>
</CompositionsContext.Provider>
);
}
export { CompositionsContext };
export default CreateComposition;
Compositions.js
import React, {useContext} from 'react';
import { Link } from 'react-router-dom';
import { CompositionsContext } from './CreateComposition'
//Fix the display
const Compositions = () => {
const compositions = useContext(CompositionsContext);
return (
<CompositionsContext.Provider value={compositions}>
<Link to='/createcomposition' className='btn'>
<h1>Create Compositions</h1>
</Link>
<p></p>
<h2>List of Compositions</h2>
<ul>
{compositions.map((composition, index) => (
<li key={index}>{composition}</li>
))}
</ul>
</CompositionsContext.Provider>
);
};
export default Compositions;
2
Answers
You try to use two separate context providers in 2 components.
In this case, each consumer will get context values from a single provider (the nearest provider up the component tree), and no context values are shared between these two components.
And, in Compositions component, you are using useContext. Here, this component or its parent component should be wrapped with context provider, not on render function.
You should use the same context instance in both components. Since you’ve exported the CompositionsContext, you can directly use it in the Compositions component without creating a new provider.