I'm trying to have the user input multiple "themes" via a form input bar so that I can add it to the database. The schema model I have created for the object has the "theme" as an array so that part's done. I'm wondering if there's a way to add multiple input values to the same state variable theme
in the code down below.
Here is what my code looks like:
import { useState } from "react";
const ProjectAdminForm = () => {
const [sdg, setSDG] = useState('')
const [goal, setGoal] = useState('')
const [orginization, setOrginization] = useState('')
const [source, setSource] = useState('')
const [location, setLocation] = useState('')
const [published, setPublished] = useState('')
const [website_url, setWebsiteURL] = useState('')
const [assignment_type, setAssignmentType] = useState('')
const [theme, setTheme] = useState('')
const [sharepoint_link, setSharepointLink] = useState('')
const [statement, setStatement] = useState('')
const [error, setError] = useState(null)
const handleSubmit = async (e) => {
e.preventDefault() // Prevents refresh of page from happening
console.log('button clicked')
const project = {sdg, goal, orginization, source, location, published, website_url, assignment_type, theme, sharepoint_link, statement}
console.log(project)
// Sending form response to backend
const response = await fetch('/api/projects', {
method: 'POST',
body: JSON.stringify(project),
headers: {
'Content-Type': 'application/json'
}
})
const json = await response.json
// Checking for error
if (!response.ok) {
setError(json.error)
}
if (response.ok) {
// Reset form inputs back to empty string
setSDG('')
setGoal('')
setOrginization('')
setSource('')
setLocation('')
setPublished('')
setWebsiteURL('')
setAssignmentType('')
setTheme('')
setSharepointLink('')
setStatement('')
setError(null)
console.log('new project added', json)
}
}
return (
<form className="create" onSubmit={handleSubmit}>
<h3>Add a New Project</h3>
<label>SDG (Num Name):</label>
<input
type="text"
placeholder="e.g. SDG 2: Zero Hunger"
onChange={(e) => setSDG(e.target.value)}
value={sdg}
/>
<label>Goal:</label>
<input
type="text"
onChange={(e) => setGoal(e.target.value)}
value={goal}
/>
<label>Orginization:</label>
<input
type="text"
onChange={(e) => setOrginization(e.target.value)}
value={orginization}
/>
<label>Source:</label>
<input
type="text"
onChange={(e) => setSource(e.target.value)}
value={source}
/>
<label>Location:</label>
<input
type="text"
onChange={(e) => setLocation(e.target.value)}
value={location}
/>
<label>Published:</label>
<input
type="text"
onChange={(e) => setPublished(e.target.value)}
value={published}
/>
<label>Website URL:</label>
<input
type="text"
onChange={(e) => setWebsiteURL(e.target.value)}
value={website_url}
/>
<label>Assignment Type:</label>
<input
type="text"
onChange={(e) => setAssignmentType(e.target.value)}
value={assignment_type}
/>
<label>Theme:</label>
<input
type="text"
onChange={(e) => setTheme(e.target.value)}
value={theme}
/>
<label>Sharepoint Link:</label>
<input
type="text"
onChange={(e) => setSharepointLink(e.target.value)}
value={sharepoint_link}
/>
<label>Statement:</label>
<input
type="text"
onChange={(e) => setStatement(e.target.value)}
value={statement}
/>
<button>Add Project</button>
{error && <div className="error">{error}</div>}
</form>
)
}
export default ProjectAdminForm
Specifically for the theme
input:
<label>Theme:</label>
<input
type="text"
onChange={(e) => setTheme(e.target.value)}
value={theme}
/>
, how can I have multiple inputs that link to the same theme
state which holds them all as an array and then gets passed on to the backend via handleSubmit
? Say a user wants to enter "magic", "joy", and "fun" as the themes, how could I make it so that all 3 of those get stored in the theme
state variable via the input form?
CodePudding user response:
You could do something like this, I guess:
const [theme, setTheme] = useState([''])
And then define a function addTheme
that would call setTheme and add a string if it's not already present in the array.
function addTheme(newTheme){
if(!theme.includes(newTheme){
setTheme([...theme, newTheme])
}
}
CodePudding user response:
As array:
const [themes, setThemes] = useState([]);
const available_themes = ['magic', 'joy', 'fun', 'more'];
const addTheme = (name) =>{
if(!themes.includes(name)){
setThemes([...themes, name])
}
}
const removeTheme = (name) =>{
const index = themes.indexOf(name);
if(index !== -1) {
let temp_themes = [...themes];
temp_themes.splice(index, 1);
setThemes(temp_themes);
}
}
const themeselector = available_themes.map((name)=>{
let checked = false;
if(themes.includes(name)){
checked = true;
}
return <div><input type="checkbox" {...(checked ? {checked: 'checked'}: {})} value={name} onClick={(ev)=>{ if(ev.target.checked) { addTheme(name) } else { removeTheme(name)} } } /> {name}</div>;
});
As object:
const [themes, setThemes] = useState({});
const available_themes = ['magic', 'joy', 'fun', 'more'];
const addTheme = (name) =>{
if(typeof themes[name] == 'undefined') {
let temp_themes = {...themes};
temp_themes[name] = name;
setThemes(temp_themes);
}
}
const removeTheme = (name) =>{
if(typeof themes[name] !== 'undefined') {
let temp_themes = {...themes};
delete temp_themes[name];
setThemes(temp_themes);
}
}
const themeselector = available_themes.map((name)=>{
let checked = false;
if(typeof themes[name] !== 'undefined'){
checked = true;
}
return <div><input type="checkbox" {...(checked ? {checked: 'checked'}: {})} value={name} onClick={(ev)=>{ if(ev.target.checked) { addTheme(name) } else { removeTheme(name)} } } /> {name}</div>;
});
<label>Select Themes</label>
{themeselector}