Allen
Allen

Reputation: 55

Function not returning component after form submit in React

I have been learning React for a couple of weeks now and I am trying to create a react app that displays a form and when submitted, it takes the inputs and creates a madlib sentence. However when I submit the form, the GenerateMadlib component does not get rendered. Any help is appreciated! ./Madlib.js

const Madlib = () => {
    const [formData, handleChange, resetFormData] = useFields({
        noun: '',
        noun2: '',
        adjective: '',
        color: ''
    })
    const handleSubmit = e => {
        e.preventDefault();
        resetFormData()
    }

    const generateMadlib = () => {
        console.log("This line runs");
        return <GenerateMadlib noun={formData.noun} noun2={formData.noun2} adjective={formData.adjective} color={formData.color} />
    }
    
    return (
        <div className="Madlibs">
            <h1>Madlibs!</h1>
            <form
            onSubmit={handleSubmit}>
                <input
                className="Madlibs-input"
                type="text" 
                name="noun" 
                value={formData.noun}
                placeholder="noun"
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="noun2" 
                value={formData.noun2}
                placeholder="nou2" 
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="adjective" 
                value={formData.adjective} 
                placeholder="adjective"
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="color" 
                value={formData.color}
                placeholder="color"
                onChange={handleChange}/>
                <button onClick={generateMadlib}>send</button>
            </form>
        </div>
    )
}

./GenerateMadlib.js

const GenerateMadlib = ({noun, noun2, adjective, color}) => {
    const madlib = Sentencer.configure({
        nounList: [noun, noun2],
        adjectiveList: [adjective, color]
    });
    return (
        <>
            <h1>Madlibs!</h1>
            <p>{madlib}</p>
        </>
    )
}

Upvotes: 0

Views: 381

Answers (2)

Wt.N
Wt.N

Reputation: 1658

Where do you want to show <Madlib /> component? Button onClick callback function cannot return component because they don't know where to show returned component. You composite components as you build blocks. Something like below code would work though I haven't tested yet.

const Madlib = () => {
    const [show, setShow] = useState(false)
    const [formData, handleChange, resetFormData] = useFields({
        noun: '',
        noun2: '',
        adjective: '',
        color: ''
    })
    const handleSubmit = e => {
        e.preventDefault();
        setShow(true)
        resetFormData()
    }
    
    return (
        <div className="Madlibs">
            <h1>Madlibs!</h1>
            <form>
                <input
                className="Madlibs-input"
                type="text" 
                name="noun" 
                value={formData.noun}
                placeholder="noun"
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="noun2" 
                value={formData.noun2}
                placeholder="nou2" 
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="adjective" 
                value={formData.adjective} 
                placeholder="adjective"
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="color" 
                value={formData.color}
                placeholder="color"
                onChange={handleChange}/>
                <button onClick={handleSubmit}>send</button>
            </form>
            {show && <GenerateMadlib noun={formData.noun} noun2={formData.noun2} adjective={formData.adjective} color={formData.color} />}
        </div>
    )
}

Or you may want to redirect using react-router-dom.

Upvotes: 2

LQR471814
LQR471814

Reputation: 41

Returning a component from an onClick callback will not append the component to the DOM. Only what returns from the functional component will be appended to the DOM. So instead you should create an array that contains all the forms generated or a value that contains the current form generated and render that array via JSX.

const Madlib = () => {
    const [formData, handleChange, resetFormData] = useFields({
        noun: '',
        noun2: '',
        adjective: '',
        color: ''
    })
    const [currentForms, setCurrentForms] = useState([])

    const handleSubmit = e => {
        e.preventDefault();
        resetFormData()
    }

    const generateMadlib = () => {
        console.log("This line runs");
        setCurrentForms(
            currentForms.push(
                (<GenerateMadlib noun={formData.noun} noun2={formData.noun2} adjective={formData.adjective} color={formData.color} />)
            )
        ) //? This updates state and re-renders with new forms
    }

    var currentForms = []
    
    return (
        <div className="Madlibs">
            <h1>Madlibs!</h1>
            <form
            onSubmit={handleSubmit}>
                <input
                className="Madlibs-input"
                type="text" 
                name="noun" 
                value={formData.noun}
                placeholder="noun"
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="noun2" 
                value={formData.noun2}
                placeholder="nou2" 
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="adjective" 
                value={formData.adjective} 
                placeholder="adjective"
                onChange={handleChange}/>
                <input
                className="Madlibs-input"
                type="text" 
                name="color" 
                value={formData.color}
                placeholder="color"
                onChange={handleChange}/>
                <button onClick={generateMadlib}>send</button>
            </form>
            {currentForms}
        </div>
    )
}

Note: I haven't tested this code so it might have errors

Upvotes: 0

Related Questions