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 ??

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.