0

I am trying to use a more concise method of declaring the initial state of my form values by declaring them in an object within useState and having them be updated by user input.

However I get the error "Uncaught TypeError: setFieldValue.providerName is not a function".

Is my approach completely wrong? or is there a small detail I am missing?

code below

import { Container, FormControl, FormControlLabel, FormLabel, Grid, InputLabel, Paper, Radio, RadioGroup, TextField } from '@mui/material';
import Button from '@mui/material/Button';
import { useCallback, useContext, useEffect, useState } from 'react';
import { AppContext } from '../../context/context';
import DatePicker from '../../elements/form/DatePicker';
import MultipleSelect from '../../elements/form/Select';
import MultipleSelectChip from '../../elements/form/SelectMulti';
import MuiTextField from '../../elements/form/TextField';

const ProjectForm = () => {
    const [fieldValue, setFieldValue] = useState({
        projectName: "",
        providerName: "",
        clientName: "",
        description: "",
        budget: 0,
    })

    const [activeButtons, setActiveButtons] = useState({
        maconomyMavenlink: false,
        maconomy: false,
        mavenlink: false
    })

    const [formActive, setFormActive] = useState(false)

    const { mavenlinkConnected } = useContext(AppContext);
    const { maconomyConnected  } = useContext(AppContext);


    const checkFormActive = () => {
        if(maconomyConnected || mavenlinkConnected){
            setFormActive(true);
        }
    }

    const checkButtonsActive = useCallback(() => {
        if (mavenlinkConnected){
            setActiveButtons({
                mavenlink: true
            })
        }
        if (maconomyConnected){
            setActiveButtons({
                maconomy: true
            })
        }
        if (mavenlinkConnected && maconomyConnected){
            setActiveButtons({
                maconomyMavenlink: true
            })
        }
    }, [])

    useEffect(() => {
        checkButtonsActive();
    },[])

    useEffect(() => {
        checkFormActive()
    }, [])
    
    const handleSubmit = () => {
        console.log("form submitted")
    }

    const handleResetForm = () => {
        setFieldValue.projectName("");
        setFieldValue.providerName("");
        setFieldValue.clientName("");
        setFieldValue.description("");
        setFieldValue.projectName("");
        setFieldValue.budget(0);
    }

    //Dummy values for time being
    const value = "value";
    const handleChange = () => {
    }

    const templates = [
        'template 1',
        'template 2',
        'template 3',
        'template 4',
        'template 5',
        'template 6'
    ]

    const groups = [
        'group 1',
        'group 2',
        'group 3',
        'group 4',
        'group 5',
        'group 6',
    ]

    const currencies = [
        'British Pound (£)',
        'United States Dollar ($)'
    ]

    const taskBilling = [
        'Fixed Fee',
        'Time & Materials'
    ]

    const taskBillingModes = [
        'Billable',
        'Non-billable'
    ]



    return(
        
        <Container>
            {formActive ? 
            <form onSubmit={handleSubmit} className="project-form-wrapper">
                <Grid container spacing={1}>
                        <Grid item xs={12}>
                            <div className="button-container">
                                <Button disabled={!activeButtons.maconomyMavenlink} variant="contained">Mavenlink+Maconomy</Button>
                                <Button disabled={!activeButtons.mavenlink} variant="contained">Mavenlink</Button>
                                <Button disabled={!activeButtons.maconomy} variant="contained">Maconomy</Button>
                            </div>
                        </Grid>
                        <Paper className="project-form">
                            <Grid container>
                                <Grid item xs={12}>
                                    <FormControl>
                                        <FormLabel id="provider-client">I am the</FormLabel>
                                        <RadioGroup    
                                            row
                                            aria-labelledby="controlled-radio-buttons-group"
                                            name="controlled-radio-buttons-group"
                                            value={value}
                                            onChange={handleChange}
                                        >
                                            <FormControlLabel value="provider" control={<Radio />} label="Provider" />
                                            <FormControlLabel value="client" control={<Radio />} label="Client" />
                                        </RadioGroup>
                                    </FormControl>
                                </Grid>
                                <Grid item xs={12}>
                                    <TextField 
                                        fullWidth 
                                        onChange={e => setFieldValue.projectName(e.target.value)}
                                        id="project-name" 
                                        label="Project Name" 
                                        variant="outlined"
                                        value={fieldValue.projectName}
                                        error={fieldValue.projectName === "" } 
                                        helperText={fieldValue.projectName === "" ? "Required" : " "}
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <MuiTextField
                                        onChange={e => setFieldValue.providerName(e.target.value)}
                                        name="provider-name"
                                        id="provider-name"
                                        label="Provider Name"
                                        width="99%"
                                        value={fieldValue.providerName}
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <MuiTextField
                                        onChange={e => setFieldValue.clientName(e.target.value)}
                                        error
                                        name="client-name"
                                        id="client-name"
                                        label="Client Name"
                                        width="100%"
                                        value={fieldValue.clientName}
                                    />
                                </Grid> 
                                <Grid item xs={12}>
                                    <MultipleSelect
                                        options={templates}
                                        label="Template"
                                        width="100%"
                                    />
                                    <InputLabel>If selected budget, currency, task billing mode will be auto configured from selected template</InputLabel>
                                </Grid>
                                <Grid item xs={12}>
                                    <MultipleSelectChip
                                        options={groups}
                                    />
                                    <InputLabel>Assign to one or more groups</InputLabel>
                                </Grid>
                                <Grid item xs={6}>
                                    <DatePicker
                                        label="Start Date"
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <DatePicker
                                        label="End Date"
                                    />
                                </Grid>
                                <Grid item xs={12}>
                                    <TextField 
                                        fullWidth 
                                        onChange={e => setFieldValue.description(e.target.value)}
                                        id="description" 
                                        label="Description" 
                                        variant="outlined" 
                                        value={fieldValue.description}
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <MuiTextField
                                        onChange={e => setFieldValue.budget(e.target.value)}
                                        name="budget"
                                        id="budget"
                                        label="Budget"
                                        width="99%"
                                        variant="outlined"
                                        value={fieldValue.budget}
                                        error={fieldValue.budget === "" } 
                                        helperText={fieldValue.budget === "" ? "Required" : " "}
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <MultipleSelect
                                        options={currencies}
                                        label="Currency"
                                        width="100%"
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <MultipleSelect
                                        options={taskBilling}
                                        label="Task Billing Mode"
                                        width="99%"
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <MultipleSelect
                                        options={taskBillingModes}
                                        width="100%"
                                        label="Task Mode"
                                    />
                                </Grid>
                                <Grid item xs={6}>
                                    <Button onClick={handleResetForm}>Reset</Button>
                                    <Button type="submit">Submit</Button>
                                </Grid>
                            </Grid>
                        </Paper>
                </Grid>
            </form>
            : <h1>Please connect to Maconomy or Mavenlink to use this feature</h1>}
        </Container>

    )
}

export default ProjectForm;
  • You could try `setFieldValue({ projectName: '' })` as that's the API. I'm not sure if that's merging, though. You may need `setFieldValue(s => ({ ...s, projectName: '' }))` etc. – Juho Vepsäläinen Jul 29 '22 at 09:00
  • Shouldn't it be ```setFieldValue(values => ({...values, providerName: e.target.value}))``` ? – Harry Jul 29 '22 at 09:03
  • @Harry Thanks that solved it! could you explain why i need the values => and then the ...values? – Michael Stubbs Jul 29 '22 at 09:26
  • @MichaelStubbs In simple terms it basically means copying other key-value pairs present in the state. Otherwise you may lose other values when adding providerName. – Harry Jul 29 '22 at 09:29

1 Answers1

1
const handleResetForm = () => {
        setFieldValue.projectName("");
        setFieldValue.providerName("");
        setFieldValue.clientName("");
        setFieldValue.description("");
        setFieldValue.projectName("");
        setFieldValue.budget(0);
    }

is wrong. use

setFieldValue({   projectName: "",
        providerName: "",
        clientName: "",
        description: "",
        budget: 0})
MR.Jeon
  • 85
  • 3
  • 12