Skip to content
Advertisement

how to pass an object as a prop in nextjs

I cant quite figure out how I am supposed to pass an object as a prop when using useState in Next JS.

I have a lorem ipsum generator that I created in javascript functions. I have a component called Paragraphs that houses it. I need to pass in two properties,

  1. a number of paragraphs.
  2. a sentence length.

The paragraph length is set by a text input where the user types in 1-10. The sentence length is set by radio buttons.

The problem I am running into is that when you input any value, the setState gets called (intentional) and it works, the problem is, it constantly works. I want to only have it update when I click my “Adventure” button to generate the data. I am unsure how to set those values to an set them as object property values and pass the object then.

Below is my code for the fields

import React, { useState } from 'react'


import Paragraph from '../components/ipsum/Paragraph.js'


export default function rpgIpsum() {

    const [paragraphNumber, setParagraphNumber] = useState(5)
    const [sentenceLength, setSentenceLength] = useState(5)
    const [data, setData ] = useState({
        outputProps: {
            paragraphNumber: 5,
            sentenceLength: 5
        }
    })

    return (
        <div>
            {data.outputProps.paragraphNumber}
            <div className="container">
                <div className="row">
                    <div className="col-md-2 d-sm-none d-xs-none d-md-block d-none">
                        {/* <img src="public/images/Bard.jpg" alt="Lorem Ipsum Bard!" className="img-fluid" /> */}
                    </div>
                    <div className="col-md-10">
                        <h2>Looking to add some fun to your filler text?</h2>
                        <h5>Let's Spiffy up your copy with some RPG inspired Lorem Ipsum!</h5>

                        <div className="form-container">
                            <p>First, select how many paragraphs you want.  
                                <input 
                                    type="text" 
                                    name="para" 
                                    value={paragraphNumber} 
                                    className="para-box" 
                                    required 
                                    onInput={
                                        event => setParagraphNumber(parseInt(event.target.value))
                                    }
                                />
                                <small id="para-box-help" className="form-text text-muted">(Max of 10)</small>
                            </p>
                            <p>Next, select the length of the sentences</p>
                            <div className="form-check form-check-inline">
                                <input 
                                    className="form-check-input" 
                                    type="radio" 
                                    name="sentences" 
                                    value="3" 
                                    required 
                                    onInput={
                                        event => setSentenceLength(parseInt(event.target.value))
                                    }
                                /> 
                                <label className="form-check-label" htmlFor="inlineRadio1">Short</label>
                            </div>
                            <div className="form-check form-check-inline">
                                <input 
                                    className="form-check-input" 
                                    type="radio" 
                                    name="sentences" 
                                    value="5" 
                                    required 
                                    onInput={
                                        event => setSentenceLength(parseInt(event.target.value))
                                    }
                                />
                                <label className="form-check-label" htmlFor="inlineRadio2">Medium</label>
                            </div>
                            <div className="form-check form-check-inline">
                                <input 
                                    className="form-check-input" 
                                    type="radio" 
                                    name="sentences" 
                                    value="7" 
                                    required 
                                    onInput={
                                        event => setSentenceLength(parseInt(event.target.value))
                                    }
                                />
                                <label className="form-check-label" htmlFor="inlineRadio3">Long</label>
                            </div>
                            <div className="form-group">
                                <button type="submit" className="btn btn-primary"   
                                    onClick={ event => "what do i do here?" ))}
                                >Adventure!</button>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="row">
                    <div className="col-12">
                        <hr />
                            <Paragraph paragraphNumber={data.outputProps.paragraphNumber} sentenceLength={data.outputProps.sentenceLength}/>
                                                
                    </div>
                </div>
            </div>
        </div>
    )
}

Advertisement

Answer

What I’d do is refactor the input functionality into a separate component and use a function prop to pass the input data to an outer component that also contains the Paragraph component, like so:

// rpgIpsum.js
export default function rpgIpsum() {
  const [settings, setSettings] = useState({
    paragraphNumber: 5,
    sentenceLength: 5
  });

  return (
    <>
      <ParagraphInput onSubmit={setSettings} />
      <Paragraph {...settings} />
    </>
  );
}

// ParagraphInput.js
export default function ParagraphInput({ onSubmit }) {
  const [paragraphNumber, setParagraphNumber] = useState(5);
  const [sentenceLength, setSentenceLength] = useState(5);

  return (
    <div>
      {/* ... */}
      <button
        type="submit"
        onClick={() => onSubmit({paragraphNumber, sentenceLength})}
      >Adventure!</button>
    </div>
  );
}

That way, settings in rpgIpsum is only updated when the button inside ParagraphInput is pressed, and not on every change of the inputs.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement