Question about React components and function nesting

so once again I’m using a very generic example just messing around in React, but I have a question on best practices. I’ve noticed in basically any tutorials I watch that when you have a component EVERYTHING is inside of the returned component. Is this generally best practice for react? Even if you have 10+ functions? Keeping all of your code and functions within that returned component? I know this may seem like a pointless question, but I was curious as to if people ever functions/blocks of code outside of the component that are returned separately. I’m really trying to understand the basic structures of React and I want to solidify some things and try to understand best practices before I continue and get lost.

Thanks again everyone.

export default function DisplayMath() {
    
    function sumOfTwo(num1, num2) {
         return num1 + num2
    }
         let total = sumOfTwo(11, 6)

    function displayTotal() {
        const totalDisplay = document.getElementsByClassName('total-display')[0]
        totalDisplay.textContent = `total: ${total}`
    }

    return (
        <div>
            <button onClick={displayTotal}>click me!</button>
            <button>Click to add 1!</button>
            <p className="total-display">total: </p>
        </div>
    )
}

Do you have an example of what you are thinking here?

picture the example above but instead of a DisplayMath component it’s a “Main” component with 10 functions and a ton of JSX making it a larger file.

is the way React works to keep everything specific to one Component even if it’s pretty large? Say for example it’s a “Main” component with a lot of content . Would you still want to keep everything within that Main function?

I guess it seems weird to me to have a ton of functions within one function being “Main” in this example.

export default function DisplayMath() {
    
    function sumOfTwo(num1, num2) {
         return num1 + num2
    }
         let total = sumOfTwo(11, 6)

    function displayTotal() {
        const totalDisplay = document.getElementsByClassName('total-display')[0]
        totalDisplay.textContent = `total: ${total}`
    }

    return (
        <div>
            <button onClick={displayTotal}>click me!</button>
            <button>Click to add 1!</button>
            <p className="total-display">total: </p>
        </div>
    )
}

export function randomFunction() {
console.log('function outside of component)}

Remember React is just JavaScript. You seem to think something is unique to React, but that is not the case. You can create as many external functions as you want. You can keep them in separate files if you want and import them as needed.

If a function is specific to a component, then it would make sense to keep that function inside the component. If the function can be used across multiple components, then it would make sense to move that function to a separate file (maybe a file full of utility functions) and import the file into multiple components where needed.

There is no hard fast rule on this. It depends on the structure of the app. You do what makes the code most readable and maintainable.

“If a function is specific to a component, then it would make sense to keep that function inside the component. If the function can be used across multiple components, then it would make sense to move that function to a separate file (maybe a file full of utility functions) and import the file into multiple components where needed.”

that cleared it up for me, thank you

I actually didn’t mess around much with import/export before React.

I’m sorry but one more thing if anyone can help, I really don’t want to make another post over something small.

another weird thing I have noticed since using Create React App is when I console log something it displays twice.

the first console log will be "(filename).js :4
the second console log will be "react devtools backend.js: 4082

I never really paid mind to it but I just added an event listener to a button to console log something and when I click the button it will console log it twice instead of once per click. Here is the code

export default function Calculator() {

    const calculateButton = document.querySelectorAll('.calculate-button')[0]
    calculateButton.addEventListener('click', () => {
        console.log('works')
    })

    return (
        <div className="calculator-container">
            <div className="calculator">
                <h1>Add Two Numbers!</h1>
                <input type="number" />
                <input type="number" />
                <button className="calculate-button">Calculate!</button>
            </div>
        </div>
    )
}

You should not be querying the DOM with querySelectorAll and should should definitely not be using addEventListener to something that has not be created yet. I am not even sure how you the code above even executes without an error.

Do you have a link to the full project code? I would like to check something.

Have you gone through the React course here yet? You use onClick attributes to do such things.

Don’t you get an error with that code?

I would expect the code to be inside a useEffect that runs on mount.


But as said, that isn’t how React works and you do not use it like that.

1 Like

@Tsmithcode To accomplish what I think you are wanting to do, you could write:

import { useState } from 'react';

function App() {
  function handleClick(event) {
   const { num1, num2 } = numbers;
    setAnswer(+num1 + +num2);
  }
  
  function handleChange(event) {
    const value = event.target.value;
    setNumbers({
      ...numbers,
      [event.target.id]: value
    })
  }

  const [numbers, setNumbers] = useState({ num1: '', num2: ''});
  const [answer, setAnswer] = useState('');

  return (
      <div className="calculator-container">
          <div className="calculator">
              <h1>Add Two Numbers!</h1>
              <input id="num1" type="number" value={numbers.num1} onChange={handleChange}/>
              <input id="num2" type="number" value={numbers.num2} onChange={handleChange}/>
              <button onClick={handleClick} className="calculate-button">Calculate!</button>
              <span id="answer">{answer}</span>
          </div>
      </div>
  )
}

export default App;

“You should not be querying the DOM with querySelectorAll and should should definitely not be using addEventListener to something that has not be created yet.”

to the first sentence, are you just saying that because it’s a single element I’m grabbing? I still need to assign elements to a name so I can use them. Using things like getElementByClassName are still fine to use, correct?

and to the second sentence, I understand my mistake here because the jsx is further down the page and I’m trying to assign a name to something that is not created yet. I’ve always seen people put their JS above the return of the component.

You should not be using any type of querySelector or getElementById methods on the DOM. React makes use of a shadow DOM, so you can end up with unexpected/unreliable results when going outside of the React methods.

You need to look through the React tutorials on https://reactjs.org/. Everything you normally did with Vanilla JS can be done in a “React Way”.

So, if I’m trying to get a jsx element such as a button or input field, how exactly would I assign a name to it so I can work with it? I’ve always used things like getElementById and assigned a name so I could manipulate it.

edit** also, I am watching that exact tutorial that lasjorg posted, I just like clearing up any confusion before continuing if I feel lost.