I've a problem by serving the resource via a json feed in fullcalendar scheduler with react. The feed works in the normal fullcalendar scheduler without react.
import React from 'react';
import FullCalendar from '#fullcalendar/react';
import resourceTimelinePlugin from '#fullcalendar/resource-timeline';
import calendarInteraction from '#fullcalendar/interaction';
class Calendar extends React.Component {
state = {};
render() {
return (
<div>
<FullCalendar
schedulerLicenseKey="GPL-My-Project-Is-Open-Source"
plugins={[calendarInteraction, resourceTimelinePlugin]}
initialView={'resourceTimelineMonth'}
selectable={true}
editable={true}
resourceAreaWidth={'10%'}
resources={"localhost/resources"}
/>
</div>
);
}
}
export default Calendar;
I get the following error in the console:
Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the CalendarDataProvider component.
It looks like a react problem, but I'm not getting it. Where does the fullcalendar react "plugin" save the state of the resources?
Sorry, I've found the answer:
It seems you have to explicitly give an absolute URL in the react fullcalendar but the fullcalendar version without react works also with non explicit URLs.
So resources={"http://localhost/resources"} works. And resources={"localhost/resources"} doesn't work!
Thanks to #ADyson who gave the answer.
Related
I am following a guide to upgrade to React 18. After completing the upgrade I am seeing errors on certain pages in my app.
ReactDOM.unstable_renderSubtreeIntoContainer() is no longer supported in React 18.
I am not using the unstable_renderSubtreeIntoContainer() function anywhere in my app, but when I look closer at what is causing these errors it seems to be caused my Bootstrap components.
Is there anyway to update this to remove the errors?
I ran into the same problem with react-bootstrap#v0.33.1 specifically when using OverlayTrigger component after upgrading to React 18. The warning message suggests to migrate to using portals. So I implemented a CustomOverlayTrigger component that leverages portals and referred to React's portal documentation to do so. Note that this solution is for Bootstrap 3 usage of OverlayTrigger (react-bootstrap v0.33.1). It seems later versions of react-bootstrap got rid of using ReactDOM.unstable_renderSubtreeIntoContainer. If you are not in a position to migrate to later versions (like I am), this solution will help for this use case. I have not check thoroughly if other components use the deprecated method, but the approach might be the same.
First of all, I copied the original source of the OverlayTrigger component code located here. You will need to clean up the imports and include into your code the utils function createChainedFunction located here.
I then created a portal wrapper based off React's documentation that looks like this:
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
const tooltipRoot = document.getElementById('tooltip-root');
class PortalWrapper extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount() {
tooltipRoot.appendChild(this.el);
}
componentWillUnmount() {
tooltipRoot.removeChild(this.el);
}
render() {
// eslint-disable-next-line react/destructuring-assignment
return ReactDOM.createPortal(this.props.children, this.el);
}
}
PortalWrapper.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]).isRequired,
};
export default PortalWrapper;
At the top, you can see the line const tooltipRoot = document.getElementById('tooltip-root');, I simply added in my index.html a div next to the react app's root div that will server as the anchor for my portal.
Then, back in the CustomOverlayTrigger component copied from react-bootstrap, I edited it in the follwing manner:
Remove all references to this._overlay and this._mountNode because the PortalWrapper now manages the mounting/unmounting. So I deleted componentDidMount(), componentDidUpdate(), componentWillUnmount() and renderOverlay()
I modified makeOverlay so that its result is wrapped by PortalWrapper so it became the following:
makeOverlay(overlay, props) {
return (
<PortalWrapper>
<Overlay
{...props}
show={this.state.show}
onHide={this.handleHide}
target={this}
>
{overlay}
</Overlay>
</PortalWrapper>
);
}
Finally, I changed the render method's return statement to become:
return (<>
{cloneElement(child, triggerProps)}
{this.makeOverlay(overlay, props)}
</>);
After this, I simply had to replace all my invocations to OverlayTrigger with CustomOverlayTrigger and I had the same result without the warning message.
I am trying to use the library 'react-images' in my reactjs project. I am receiving the error "Unexpected token" in the react-images\src\components\Footer.js file. Also, on the same line i have the error "'import ... =' can only be used in a .ts file.".
import type { PropsWithStyles, ViewType } from '../types';
Also, I am receiving the error "'type aliases' can only be used in a .ts file." in many of the component files in 'react-images' library. Why is this? Thanks.
import React, { Component, Fragment } from 'react';
import Carousel, { Modal, ModalGateway, FooterCaption } from 'react-images';
You misunderstand how this library is designed. If you look at the documentation, FooterCaption is listed under Component API. That means FooterCaption is part of the API for the Carousel component meaning that this is designed with the Slots Pattern.
If you look at the example code above it, it shows you how this works.
<Carousel components={{ Header: CustomHeader }} />
The Carousel component has a prop called components which takes an object. This object is expected to have keys that are one of the various replaceable components listed under Component API. The value is expected to be a something that React can render; typically a component. This example is replacing the Header with a custom header component called CustomHeader.
If you don't override the component, then Carousel will render something by default as described in the documentation for each component under Component API.
If you would like to override the default FooterCaption, then you will do something like this:
<Carousel components={{ FooterCaption: MyCustomFooterCaption }} />
Where MyCustomFooterCaption is a component you've defined elsewhere. The props it will receive from the Carousel component can be found in the source code.
To summarize:
You don't need to import FooterCaption.
If you plan on overriding the default FooterCaption, then create your own component and pass it in as shown in example.
The same goes for everything listed under Component API.
Have a ReactJS + Redux + Saga application that was recently updated to use the latest (or close to latest) versions of the respective JS libraries. After the library updates (no code changes) and running the application, I immediately see the "Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state." warning message in the console. It looks to be triggered by redux when I invoke the dispatch function (which then calls a function in Provider.js, then goes through react-dom, and then in turn writes the warning message. Again nothing in my code has changed, and my code is essentially built using stateless functions.
Not sure how to go about figuring out what is causing this warning-- although the app still runs ok as expected. Using React 16.8.6, react-redux 6.0.1, react-router-dom 5.0.0, redux 4.0.1, redux-saga 1.0.2, and connected-react-router 6.4.0.
Below is a sample page that would cause the warning message:
import React from 'react'
import {connect} from 'react-redux'
import {links} from '../links'
import {notify} from '../notifications'
const Home = props => {
const {dispatch} = props
return (
<main>
<p>
Go to Details...
</p>
</main>
)}
const dispatcher = dispatch => {
dispatch(notify(links.HOME))
return {dispatch}
}
export default connect(null, dispatcher)(Home)
You cannot call to dispatch inside the disaptcher function.
react-redux's connect parameters are:
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
mapDispatchToProps is what you called dispatch. These params are eventually run as functions that called in the render loop of the connected component. When you dispatch in the render loop it changes the state of a React component (looks like it's the Provider), which is forbidden by React.
Solution
Move the dispatch(notify(links.HOME)) to lifecycle method. For example you can add to the Home component (this will require to rewrite the Home component as an extension of React.Component class:
componentDidMount() {
dispatch(notify(links.HOME))
}
UPDATE
If you want to do this with classless component see that question
I'm attempting to use react-dnd and react-big-calendar with drag-n-drop support (using react-dnd under the hood as well) in an app together. However, if I initiate them separately, I get an error:
Uncaught Error: Cannot have two HTML5 backends at the same time.
Here's the code:
App.js
import React from 'react'
import {DragDropContext} from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import Calendar from './Calendar'
class App extends React.Component {
render() {
return {
<div>
...
<Calendar />
</div>
}
}
}
export default DragDropContext(HTML5Backend)(App)
Calendar.js
import React from 'react'
import BigCalendar from 'react-big-calendar'
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'
const Calendar = withDragAndDrop(BigCalendar)
...
react-big-calendar documentation mentions that the withDragAndDrop() function can accept a backend as a second argument, meaning, in theory, I should be able to retrieve the backend instance that I have already set for react-dnd and pass it as an argument. However, I'm not sure how I retrieve the backend instance.
react-dnd documentation for DragDropContext mentions an instance method getManager() which should help me retrieve the backend (getManager().getBackend()). However, the key here is instance method. How do I get the instance of DragDropContext(HTML5Backend)(App) from my Calendar.js file?
I'm using React Native which ships with React 16 alpha release which supports portals. While in browser and having access to DOM we can use id or classes to access element from anywhere in component/file hierarchy like this:
const modalRoot = document.getElementById('modal-root');
and pass it to createPortal(child, container) container arg. React docs clearly says than container should be DOM element:
The second argument (container) is a DOM element.
This function is also a method of ReactDOM which doesn't exist in React Native.
Is there a way to achieve the similar functionality in React Native?
Use case:
I want to render an animated overlay in the root of my application but pass the Animated values props to it from a parent deep in the tree hierarchy (can't use Redux actions for such things).
I had similar problem where I wanted to render overlay on top of everything from deeply nested child component. I solved my problem with React Native's Modal
It renders its content on top of everything :) Easy to use and no need for extra dependencies
I don't think react-native provides this functionality in its own API.
But there is a library available which provides the similar functionality. react-gateway
As per the docs of react-gateway,
It also works in universal (isomorphic) React applications without any additional setup and in React Native applications.
React Gateway does not directly depend on react-dom, so it works fine with React Native under one condition:
You must pass React Native component like View or similar to component prop of .
import React from 'react';
import { Text, View } from 'react-native';
import {
Gateway,
GatewayDest,
GatewayProvider
} from 'react-gateway';
export default class Application extends React.Component {
render() {
return (
<GatewayProvider>
<View>
<Text>React Gateway Native Example</Text>
<View>
<Gateway into="one">
<Text>Text rendered elsewhere</Text>
</Gateway>
</View>
<GatewayDest name="one" component={View} />
</View>
</GatewayProvider>
);
}
}
The above example is taken from the repo itself. react native example
One way to render the items above the screen can be done using react-native-paper library.
import * as React from 'react';
import { Text } from 'react-native';
import { Portal } from 'react-native-paper';
const MyComponent = () => (
<Portal.Host>
<Text>Content of the app</Text>
</Portal.Host>
);
export default MyComponent;
Portal host renders all of its children Portal elements. For example, you can wrap a screen in Portal.Host to render items above the screen.
Here is the link which describes its usage:
https://callstack.github.io/react-native-paper/portal-host.html