0

I'm trying to make a timer in React but, I have a problem. The error that I am getting is this:

Uncaught TypeError: Cannot read property 'seconds' of undefined'.

I have tried to understand but, I can't find the problem.

Can someone help me ?

Here is the fiddle : https://jsfiddle.net/q806zeps/17/

Thank you.

I think the problem is here because if I comment the render, it's ok.

<TimerInput 
    value={this.state.seconds} 
    handleChange={this.handleChange} 
/> 
<Minuteur 
    seconds={600} 
    libelle="Pâtes"
/>```

1
  • That error means you are trying to read the seconds field of something before it has been defined. There's nothing there yet. This problem arises a lot. (BTW, this is a problem that cannot arise in some static typed languages, such as Haskell, because they make it impossible to create a thing that has no value.) Commented Nov 17, 2018 at 16:06

4 Answers 4

2

In addition to Levi's answer (as I'm not allowed to comment yet):

Your TimerInput component is trying to read prop seconds (not value), so your render line for it should look like:

<TimerInput seconds={this.state.seconds} handleChange={this.handleChange} />
Sign up to request clarification or add additional context in comments.

Comments

1

The problem is that you are trying to access the state and methods of the Minuteur component from the parent component App.

const App = () => {
    return (
    <div>
      <TimerInput value={this.state.seconds} handleChange={this.handleChange} />
      <Minuteur seconds={600} libelle="Pâtes"/>
    </div>
  )
}

this.state.seconds and this.handleChange refer to attributes on the Minuteur component. Since it seems like TimerInput and Minuteur need to share some state, you have a couple options.

  1. Combine the TimerInput and Minuteur components into one so they have the same state.
  2. Create a wrapping component that contains both TimerInput and Minuteur and move the shared state (e.g. state.seconds) to that component.

The approach for option 2 would look roughly like this:

class Wrapper extends React.Component {
  constructor(props) {
    super(props)
    this.state = { 
      seconds: 0
    }

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({
      seconds: event.target.value
    })
  }

  render() {
    return (
      <div>
        <TimerInput value={this.state.seconds} handleChange={this.handleChange} />
        <Minuteur seconds={this.state.seconds} libelle="Pâtes"/>
      </div>
    )
  }


const App = () => {
  return (
    <div>
      <Wrapper />
    </div>
  )
}

3 Comments

Thanks but I have this error now... react-dom.development.js:49 Uncaught Error: Wrapper(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.jsfiddle.net/q806zeps/26
I can't see your error, but see MrAleister's answer for another correction you need to make. I just updated my answer with it.
I missed a return statement in render(). Answer has been updated.
0

Just add return to the Wrapper's render:

render() {
  return(
    <div>
      <TimerInput seconds={this.state.seconds} handleChange={this.handleChange} />
      <Minuteur seconds={this.state.seconds} libelle="Pâtes"/>
    </div>
  )
}

Comments

0

Quick and dirty solution - set initial Wrapper seconds state to anything but 0 (like 600 you had in your original fiddle):

this.state = { 
  seconds: 600
}

3 Comments

Yes but I want the input change in real time the seconds ;)
Ok - issue is with your TimerInput component lacking the state. Here is an answer for it: stackoverflow.com/questions/37427508/…
I need to add a constructor on TimerInput ??

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.