Cannot read properties of null (reading 'getApi') in FullCalendar.io reactjs - javascript

i'm new to ReactJs and i'm trying to class component of FullCalendar to a functional component i watched some tutorials but when i did it i keep getting this error
Uncaught TypeError: Cannot read properties of null (reading 'getApi')
and i searched for a functional component for the FullCalendar but i didn't find anything useful
this is my class component:
import React from "react";
import FullCalendar from "#fullcalendar/react";
import './Fullcalendar.css'
import dayGridPlugin from "#fullcalendar/daygrid";
import interactionPlugin from "#fullcalendar/interaction"; // needed for dayClick
export default class DemoApp extends React.Component {
calendarComponentRef = React.createRef();
state = {
calendarWeekends: true,
calendarEvents: [
// initial event data
{ title: "Event Now", start: "2022-03-21", backgroundColor: "red" }
]
};
render() {
setTimeout(() => {
let calendarApi = this.calendarComponentRef.current.getApi();
calendarApi.gotoDate(this.props.date); // call a method on the Calendar object
});
return (
<div>
<div className="demo-app">
<div className="demo-app-calendar">
<FullCalendar
id="fullCalendar"
contentHeight={720}
firstDay={1}
defaultView="dayGridMonth"
plugins={[dayGridPlugin, interactionPlugin]}
ref={this.calendarComponentRef}
events={this.state.calendarEvents}
/>
</div>
</div>
</div>
);
}
}
and this is what i did to converted to a functional component:
import React, { useRef } from "react";
import FullCalendar from "#fullcalendar/react";
import './Fullcalendar.css'
import dayGridPlugin from "#fullcalendar/daygrid";
import interactionPlugin from "#fullcalendar/interaction"; // needed for dayClick
function Fullcalendar({date}) {
const calendarComponentRef = useRef(null);
setTimeout(() => {
let calendarApi = calendarComponentRef.current.getApi();
calendarApi.gotoDate(date);
});
return (
<div>
<div className="demo-app">
<div className="demo-app-calendar">
<FullCalendar
id="fullCalendar"
contentHeight={720}
firstDay={1}
defaultView="dayGridMonth"
plugins={[dayGridPlugin, interactionPlugin]}
ref={calendarComponentRef}
/>
</div>
</div>
</div>
)
}
export default Fullcalendar
i tried and i searched but i don't know what i have to do.

It seems that you are setting a timeout which has no time associated, so it will run immediately. It tries to get the calendar component, but that seems to be before you've even returned the calendar component from your function, so I would expect that the calendar object doesn't exist yet, which is why your code can't find it.
Also, all you're doing with that API object is immediately setting the calendar date, but that's something you can do directly within the calendar options, if you want the calendar to start at a specific date.
Why not simply add
initialDate={date}
to the options in the <FullCalendar section instead?

I had your same problem. We can reach this api only after your component finishes rendering calendar. So when I put it in useEffect, it worked!
import React, { useRef } from "react";
import FullCalendar from "#fullcalendar/react";
import './Fullcalendar.css'
import dayGridPlugin from "#fullcalendar/daygrid";
import interactionPlugin from "#fullcalendar/interaction"; // needed for dayClick
function Fullcalendar({date}) {
const calendarComponentRef = useRef();
useEffect(() => {
let calendarApi = calendarComponentRef.current.getApi();
calendarApi.gotoDate(date);
});
return (
<div>
<div className="demo-app">
<div className="demo-app-calendar">
<FullCalendar
id="fullCalendar"
contentHeight={720}
firstDay={1}
defaultView="dayGridMonth"
plugins={[dayGridPlugin, interactionPlugin]}
ref={calendarComponentRef}
/>
</div>
</div>
</div>
)
}
export default Fullcalendar

Related

React Props not passing down to children components?

I am trying to learn React so please bear with me!
I am following a tutorial to help me understand react and how you can pass down components.
I am trying to pass props down 2 levels, but when I render the code on the third element, nothing appears on the page. Using React Dev tools on chrome, it seems that the props are loading on the Tweets.js component rather than the Tweet.js component.
Can anybody tell me whats wrong? The order is App.js > Tweets.js > Tweet.js
For ref, I am following the following tutorial, it is around the 15 min mark.
React State and Props | Learn React For Beginners Part 4
App.js
import './App.css';
import Tweets from './components/Tweets';
import React from 'react';
function App() {
const name=["Name1", "Name2", "Name3"];
const age=["21", "22", "24"]; /* Data is created here */
return (
<div className="App">
<Tweets me={name} age={age} />{/*Data is added to component*/ }
</div>
);
}
export default App;
Tweets.js
import Tweet from './Tweet';
const Tweets = (props) => (
<section>
<Tweet />
</section>
);
export default Tweets;
Tweet.js
const Tweet = (props) => (
<div>
<h1>{props.me}</h1>
<h1>{props.age}</h1>
</div>
);
export default Tweet;
You would need to transfer props through your Tweets component:
const Tweets = (props) => (
<section>
<Tweet {...props} />
</section>
);

How do I properly use keys with React functional components? Here's my like button:

I'm trying build a Facebook-esque like button with React to get a better handle on stateful components. I'm not sure what the problem is, but I think it's the keys.
Error: Objects are not valid as a React child (found: object with keys {numLikes, onSelect}). If you meant to render a collection of children, use an array instead.
in p (at LikeButton.js:8)
in LikeButton (at App.js:10)
in App (at src/index.js:9)
in StrictMode (at src/index.js:8)
Here's App.js:
import React, { useState } from 'react';
import './App.css';
import LikeButton from './components/LikeButton';
function App() {
const [likes, updateLikes] = useState(23);
const [liked, updateLiked] = useState(false);
return (
<LikeButton
secret='like-button'
numLikes={likes}
// status={liked}
onSelect={(liked) => {
if (liked) {
updateLikes(likes + 1);
} else { updateLikes(likes - 1)
};
updateLiked(!liked);
}
}
/>
// onClick function here, or in LikeButton.js?
);
}
export default App;
Here's LikeButton.js:
import React from 'react';
import FaThumbsUp from 'react-icons/fa';
export default function LikeButton(secret, numLikes, onSelect) {
return (
<>
<div key={secret} onClick={onSelect}>Like Button</div>
<p>{numLikes}</p>
</>
);
}
When using properties in functional component you need to destruct the props, not take them individually. Because properties of a component are the first parameter in the function
import React from 'react';
import FaThumbsUp from 'react-icons/fa';
export default function LikeButton({secret, numLikes, onSelect}) {
return (
<>
<div key={secret} onClick={() => onSelect(true)}>Like Button</div>
<div key={secret} onClick={() => onSelect(false)}>Dislike Button</div>
<p>{numLikes}</p>
</>
);
}
When you get a error of this type, know that you are trying to render a property or variable that is not a React element or non-object type data.
secret, numLikes, onSelect are inside of props object. you should destruct before use.
const {secret, numLikes, onSelect} = props

how to destroy animation in bodymovin react

So I'm trying to destroy the animation in my react app but it is not destroying if I use any event listener I get the errors I don't know why, here is the code
import React, { Component } from 'react';
import './Cool.css';
import data from './data.json';
import ReactBodymovin from 'react-bodymovin';
class AventadorPage extends Component {
render() {
var bodymovinOptions = {
loop: 2,
autoplay: true,
prerender: true,
animationData: data,
}
return (
<div id="main-container">
<div className="animation">
<ReactBodymovin options={bodymovinOptions} />
</div>
</div>
);
}
}
export default AventadorPage;

How to have text dynamically change with React, but not call the change in Render?

I'm trying to build a very simple app with React that will tell you how many days have past since a given date. I am using React, Moments, and ReactJS Datepicker as the foundation of this app for quick implementation.
I'm getting an error when I attempt to pick a date saying
warning.js:44
Warning: setState(...): Cannot update during an existing state transition (such as within 'render' or another component's constructor)
I understand it means I can't have a function update a state I am currently displaying due to render issues, but am having a hard time figuring out how I can get such functionality without updating it in the render method.
This is the current app:
import React, { Component } from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import './App.css';
import 'react-datepicker/dist/react-datepicker.css';
class App extends Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this)
this.state = {
startDate: moment(),
dateDiff: moment(),
dateCheck: false
};
}
handleChange(date) {
this.setState({
startDate: date,
dateCheck: true
});
}
showDiff(date, dateCheck) {
if (dateCheck) {
this.setState({
dateCheck: false,
dateDiff: moment().startOf(date).fromNow()
});
}
}
render() {
return (
<div className="App">
<div className="DatePicker">
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}
showYearDropdown
dateFormatCalendar="MMMM"
isClearable={true}
placeholderText='Enter A Date' />
</div>
<div>
{this.showDiff(this.state.startDate, this.state.dateCheck)}
</div>
</div>
);
}
}
export default App;
I'm trying to have it update the number of calculated days every time a new date is selected, and thought the dateCheck flag would help, but it didn't.
Thanks
React automatically re-renders parts of the DOM that need updating upon state change. The idea is to tell React what you want it to render, not how you want it to render.
So in your case, if you just want React to render the date difference from now, you need only change startDate when it updates. Here's some code to try to illustrate what I'm suggesting:
import React, { Component } from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import './App.css';
import 'react-datepicker/dist/react-datepicker.css';
class App extends Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this)
this.state = {
startDate: moment()
};
}
handleChange(date) {
this.setState({
startDate: date
});
}
render() {
return (
<div className="App">
<div className="DatePicker">
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}
showYearDropdown
dateFormatCalendar="MMMM"
isClearable={true}
placeholderText='Enter A Date' />
</div>
<div>
{this.state.startDate.fromNow()}
</div>
</div>
);
}
}
export default App;

React-on-Rails, passing and formatting props?

I'm trying to pass a collection of events objects down to a react-big-calendar component. I'm working from an example, and I'm very close - but there is something I'm missing. It is easier if I explain further with code examples:
Here is where the props are being passed in from the rails view. #events, is an array of event objects. The events will need to be formatted so they can be displayed in big calendar at some point:
<%= react_component("CalendarApp",
props: #events,
prerender: false) %>
This component is being passed to ReactOnRails.register in the following snippet:
import React from 'react';
import Calendar from '../containers/Calendar';
export default (props) => (
<Calendar {...props} />
);
Here is where 'CalendarApp' is being made available in the rails views:
import ReactOnRails from 'react-on-rails';
import CalendarApp from './CalendarAppClient';
ReactOnRails.register({ CalendarApp });
Next, is the Calendar container/smart component. The console.log(this.props) returns the following in the browser console:
Question How do I pass props down so that I can say something like 'this.props.events' in the following 'Calendar' component, and iterate through the list? Formatting the events so they can be passed to the MyCalendar presentation component in the correct format?
import React, { PropTypes } from 'react';
import MyCalendar from '../components/bigCalendar';
import _ from 'lodash';
// Simple example of a React "smart" component
export default class Calendar extends React.Component {
componentDidMount(){
console.log("mounted");
console.log(this.props);
};
render() {
return (
<div>
<MyCalendar events={this.props}/>
</div>
);
}
}
client/app/bundles/HelloWorld/components/bigCalendar.jsx
Ultimately I want to pass #events down to this component, my instinct is to figure out how to format the events in the container component above and pass down properly formatted events to the MyCalendar presentation component. Presently, I am using test data..which is why you see import events from './events';
import React, { PropTypes } from 'react';
import BigCalendar from 'react-big-calendar';
import moment from 'moment';
import events from './events';
BigCalendar.setLocalizer(
BigCalendar.momentLocalizer(moment)
);
const MyCalendar = props => (
<div className="calendar-container">
<BigCalendar
events={events}
scrollToTime={new Date(1970, 1, 1, 6)}
defaultDate={new Date(2015, 3, 12)}
defaultView='month'
defaultDate={new Date(2015, 3, 12)}
/>
</div>
);
export default MyCalendar;
First you need to correct you .erb react_component props
<%= react_component("CalendarApp",
props: {events: #events},
prerender: false) %>
Next you want to pass your this.props as a stringified object from the constructor
constructor(props) {
super(props);
this.state= {
examples: JSON.stringify(this.props.examples)
};
}
Something to that sort if you have an array of events using ES6 syntax you could do loop through this.state
var examples = this.state
examples = this.props.examples.map((example) => {
return(
<div key={example.id}>{example.name}</div>
);
});
Then you'll need to pass your newly created loop where ever you want it
return(
<div class="col-md-10">
{examples}
</div>
);
and bam! you've got it! just remember to pass the data from your .erb controller

Categories

Resources