I am working on my personal Portfolio using React and I want to add a statement on the landing page that displays my local time and timezone to recruiters, as seen below:
I have implemented this using the date-fns library but I am currently facing one issue. As time goes by, the time values on the screen stay constant and do not update themselves automatically. As we speak, it is currently 16:58 but the time still shows 16:47. I have to do a manual refresh for the updated time values to show. I want to implement this in such a way that the time will update every 60 seconds and show the current time always.
I wrote this Class component to implement the feature:
export class Time extends Component {
constructor() {
super();
var today = new Date();
var time = format(today, 'HH:mm')
this.state = {
currentTime: time
}
}
render() {
return (
<div className="time">
<p>
My Local Time is { this.state.currentTime } GMT +3
</p>
</div>
);
}
}
setInterval(Time, 60000);
What could I do to make this possible?
I tried using the solution provided Luke-shang-04 but I ran into issues with declaration of the intervalId variable. I therefore resorted to using React Hooks and converted this component into a Functional component.
The code below works:
export const Time = () => {
const [time, setTime] = useState(new Date());
useEffect(
() => {
const intervalId = setInterval(() => {
setTime(new Date());
}, 60000);
return () => {
clearInterval(intervalId)
}
}
)
return(
<div>
<p>{`My local time is ${format(time, 'HH:mm')} GMT+3`} </p>
</div>
)
}
Create a componentDidMount method, and place the setInterval in there. Make sure that the setInterval updates this.state.currentTime. It's also a good idea to clear the interval afterwards, so store the interval id and then call clearInterval in componentWillUnmount.
Something like this
export class Time extends Component {
intervalId
constructor() {
super()
var today = new Date()
var time = format(today, "HH:mm")
this.state = {
currentTime: time,
}
}
componentDidMount() {
var today = new Date()
var time = format(today, "HH:mm")
intervalId = setInterval(() =>
this.setState({
currentTime: time,
}),
60000
)
}
componentWillUnmount() {
clearInterval(intervalId) // Clear interval to prevent memory leaks
}
render() {
return (
<div className="time">
<p>My Local Time is {this.state.currentTime} GMT +3</p>
</div>
)
}
}
I would suggest that you read up on the React Docs, since these are the basics of React.
I was trying to clean up this react component by extracting fillCalendar() from being a method of the component into it's own js file and importing it instead. Originally this.state.datesArray was set in a componentWillMount() lifecycle method. Now I'm trying to directly initialize it inside the constructor because this is what the react docs recommends. Doing it this way now throws a "TypeError: Object(...) is not a function" error and I don't know why. Here is what Calendar.js use to look like see here.
Calendar.js
import React, { Component } from 'react';
import { fillCalendar } from '../calendar.tools'
class Calendar extends Component {
constructor(props) {
super(props)
this.state = {
datesArray: fillCalendar(7, 2018),
date: new Date(),
monthIsOffset: false,
monthOffset: new Date().getMonth(),
yearOffset: new Date().getFullYear()
}
}
render() {
return (
...
)
}
}
calendar.tools.js
let fillCalendar = (month, year) => {
let datesArray = []
let monthStart = new Date(year,month,1).getDay()
let yearType = false;
let filledNodes = 0;
// Check for leap year
(year%4 === 0) ?
(year%100 === 0) ?
(year%400) ? yearType = true : yearType = false :
yearType = true :
yearType = false
const monthArrays = yearType ? [31,29,31,30,31,30,31,31,30,31,30,31] : [31,28,31,30,31,30,31,31,30,31,30,31]
if (month === 0) { month = 12; }
let leadDayStart = monthArrays[month-1] - monthStart + 1
// Loop out lead date numbers
for (let i = 0; i < monthStart; i++) {
datesArray.push({date: leadDayStart, type: "leadDate", id: "leadDate" + i})
leadDayStart++
filledNodes++
}
if (month === 12) { month = 0; }
// Loop out month's date numbers
for (let i = 0; i < monthArrays[month]; i++) {
datesArray.push({date: i + 1, type: "monthDate", id: "monthDate" + i})
filledNodes++
}
// fill the empty remaining cells in the calendar
let remainingNodes = 42 - filledNodes;
for (let i = 0; i < remainingNodes; i++) {
datesArray.push({date: i + 1, type: "postDate", id: "postDate" + i})
}
return datesArray
}
It looks fine, you just have to export your function that's it.
use
export let fillCalendar = (month, year) => {
instead of
let fillCalendar = (month, year) => {
Just putting it out there....
I saw this error because I imported a function from the wrong module!
But I'm sure you'd never do that ;-)
(obviously a bit unlucky in that the function I imported had a common name - useParams in my case)
I also got object(...) is not a function. The reason was I was importing useSelector from react instead of importing from react-redux. Found out after half an hour of continuous state.
In addition to the accepted answer, I have observed that this error more generally occurs when the module/object being imported doesn't exist. I experienced it while trying to import a component of a library that had since removed the component. In my case, the specific component was FirebaseRealTimeSaga that is no longer available in the React Admin Firebase package
Example for Higher Order Component
Export function directly from after declaration
export default function Authorized(WrappedComponent) {
}
Accidentally invoking my exported function led to the same error.
// Bad! The () invokes the getFaq function.
export default getFaq();
"Object(…) is not a function"
// Good! getFaq is not invoked.
export default getFaq;
When I tried to utilize hooks (specifically: useState()) with an older version of react in one of the projects worked on, I got the same error.
Based on dependencies into package.json I had it version 16.2.0 of react.
In my case this error happened because Hooks are used starting from: React 16.8
Below I describe the situation also with a screenshoot.
Hello everyone so I encountered the same issue of Object(...) is not a function. ( In build environment ) if it's working for you in dev but not build this is the solution.
It turns out that for my case I was using react Hooks: useState,useContext... from a development version of react
import { useContext } from 'react/cjs/react.development';
this line is what's causing the issue simply change it to :
import { useContext } from 'react';
and that will solve the issue problem.
I encountered the"Object(…) is not a function" error due to an incorrect file extension.
Adding ".js" to the file extension resolved this error.
I also got object(...) is not a function. The reason was I was importing useSelector from react instead of importing from react-redux. Found out after half an hour of continuous state.
I hope you will not do this mistake
If all else looks okay, make sure your file that you are exporting from is actually saved with your latest changes.
This error commonly does occur because you aren't actually importing the function. I validated that I was exporting my function properly and importing it properly, among all other general "gotchas".
It was only after thirty minutes of analysis that I realized I didnt actually Save the file that contained the newly added export code! So indeed, the function wasn't importing - but not due to code error, but due to human/IDE issue. I simply forgot to hit Ctrl+S and never noticed the "unsaved changes" dot on my file in Visual Studio Code.
Sounds obvious - but I know this will help others like me who may have missed the obvious.
you will have to import fillCalendar like this.
import fillCalendar from '../calendar.tools'
so you have to remove curly brackets in import statement.
This question already has answers here:
Unable to access React instance (this) inside event handler [duplicate]
(19 answers)
Closed 6 years ago.
I am trying React with ES6, and I am stuck at a point where I am trying to call a function on click of a button, and from that function I need to call another function inside that component only, How do we do that?
Here :
import React from 'react';
export default class StopWatch extends React.Component {
constructor (props) {
super(props);
this.state = {
elapsed : 0,
timer : 0,
isStart : false
}
}
onStartClick () {
setInterval(
() => this.tick1(), 100
);
}
tick1 () {
console.log('tick starts');
}
getTimeSpan (elapsed) {
let m = String(Math.floor(elapsed/1000/60)+100).substring(1);
let s = String(Math.floor((elapsed%(1000*60))/1000)+100).substring(1);
let ms = String(elapsed % 1000 + 1000).substring(1);
return m+":"+s+"."+ms;
}
onResetClick () {
console.log('on click of reset');
}
render() {
return (
<div>
<h1>{this.getTimeSpan(this.state.elapsed)}</h1> <br/>
<button type="button" onClick={this.onStartClick}>Start</button>
<button type="button" onClick={this.onResetClick}>Reset</button>
</div>
);
}
}
I am calling a function "onStartClick" on click of my start button, and inside "onStartClick" function, I am trying to call tick() function, which is giving me an error.
Can anyone suggest me how can we do that ?
What you're after is rebinding. Do it in your constructor once and you'll be set for wherever you want to use that function:
constructor (props) {
super(props);
this.state = {
elapsed : 0,
timer : 0,
isStart : false
}
this.onStartClick = this.onStartClick.bind(this)
this.onResetClick = this.onResetClick.bind(this)
}
For a full understanding of what's going on here, read this: http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/
Understanding how this works is crucial for react - and for all javascript programming.
This is my mixin in Vue.js:
var myMixin = {
data () {
clockInt: '',
clock: '',
currentTime: new Date()
},
mounted () {
this.intervalSetup();
},
methods: {
intervalSetup () {
var _this = this;
// init
this.getTime();
// start interval every 60s
this.clockInt = setInterval(
_this.getTime(), 60000
);
},
getTime () {
var now = this.currentTime,
h = now.getHours(),
m = now.getMinutes();
this.clock = h + ':' + m;
}
}
};
This should display a simple digital watch which sets the time every 60s.
Then, I register this mixin to Vue, require my component and start a new instance of Vue:
Vue.component('comp', require('./components/MyComponent.vue'));
Vue.mixin(myMixin);
const app = new Vue({
el: '#app'
});
My component looks like this:
<template>
<div>{{ clock }}</div>
</template>
<script>
export default {
data () {
return {
someData: []
}
},
mounted () {
// call methods
},
methods: {
// some methods
}
};
</script>
The first init of the mixin method works fine and as I can see in the Vue dev-tool, all data is present too. But it does not refresh the data in the interval I set up.
Hopefully someone had similar issues and can help me with this.
Well guys. Both solution work exactly as expected - as a single component and as a mixin. Good to know.
The issue was currentTime: new Date(). The date time was declared in data object only once. So the interval always took this timestamp.
I just removed this and changed var now = new Date(); in my mixin's method.
Thank you guys!
var Timeframe = React.createClass({
getInitialState: function() {
return {
tfs: getParameterByName('tfs'),
tfe: getParameterByName('tfe')
}
},
formatTime: function(time) {
var full = new Date(time);
console.log(time);
console.log(full);
return (full).toString('dddd, MMMM ,yyyy');
},
render: function () {
return (
<div>Timeframe: {this.formatTime(this.state.tfs)} - {this.formatTime(this.state.tfs)}</div>
);
}
});
I have an outside js function called getParameterByName which, in these cases, is going to return a time in unix time. As far as I know, Date() works very well with these numbers, and in my experience outside of React, I've never had any trouble with this. When I try using Date within my react function, it's returning invalid date. Does anybody know why this might be happening?
Try this: full.toString('dddd, MMMM ,yyyy');
Instead of: (full).toString('dddd, MMMM ,yyyy');
If you need to work with date, a good choice is to use Moment library.