Implementing react-tridi 360 product viewer in Next JS - reactjs

I've been looking for a good 360 product viewer library and I came across react-tridi. According to the library documentation you need to simply insert a <Tridi/> component and pass in some props. The issue that I'm facing, however, is the that I'm getting a "window not defined" error message. I read that this is due to Server Side Rendering where window is not available. As a workaround I've tried to use Next Dynamic in the following way but I still can't make it work.
import React from "react";
import Tridi from "react-tridi";
import dynamic from "next/dynamic";
const DynamicComponentWithNoSSR = dynamic(
() => {
return <Tridi location="../public/spin" format="jpg" count="120" />;
},
{
ssr: false,
}
);
function Collection() {
return (
<div className="w-96">
{" "}
<DynamicComponentWithNoSSR />
</div>
)
}

Related

Some react Lottie Animations code-splitted with loadable crash on Gatsby development but work in prod

in our project we have around 10 animations that are using react-lottie library and are loaded with loadable-component library. Some of these animations are crashing on Gatsby development environment. I have managed to narrow down which ones are failing on my end and there were 2.
The component is built like this:
#LottieComponent.tsx
import React, { CSSProperties } from 'react';
import Lottie from 'lottie-react';
import json from './lottieAnimation.json';
interface Props {
styles?: CSSProperties;
}
export default ({ styles }: Props) => (
<Lottie style={styles} animationData={json} />
);
Then we use code splitting:
#index.tsx
import loadable from '#loadable/component';
const ExchangeInfographic = loadable(
() => import('./animationComponents/ExchangeGraphic')
);
export {
ExchangeInfographic
};
Then we import the component into the module like this:
import { ExchangeInfographic } from '../../components/Infographic';
const ExampleComponent = () => {
const [animationWasRendered, setAnimationWasRendered] = useState(false);
return (
<ReactVisibilitySensor
onChange={(isVisible) => {
isVisible && setAnimationWasRendered(true);
}}
partialVisibility
>
<SectionCustomComponent>
<Container>
<Col>
{animationWasRendered ? <ExchangeInfographic /> : <></>}
</Col>
</Row>
</Container>
</Section>
</ReactVisibilitySensor>
);
};
export default ExampleComponent;
The error that I get in the console is:
react-dom.development.js:23966 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `InnerLoadable`.
I have check the possible reasons for this error message and found this thread:
https://github.com/facebook/react/issues/13445
and
Code splitting/react-loadable issue
but it doesn't look as if the dynamic import would fail. The confusing part is that, why would it only crash on some animations and the other work fine every time. O.o
Would you have an idea what am I missing?
Thanks for any suggestions!
I'm not sure if it will fix the issue because I don't know all the specs nor your use-case, but this export seems odd to me:
#index.tsx
import loadable from '#loadable/component';
const ExchangeInfographic = loadable(
() => import('./animationComponents/ExchangeGraphic')
);
export {
ExchangeInfographic
};
Have you tried something like:
#index.tsx
import loadable from '#loadable/component';
const ExchangeInfographic = loadable(
() => import('./animationComponents/ExchangeGraphic')
);
export ExchangeInfographic
So after few months I decided to give it another try at this weird bug.
Explanation of the issue:
ExchangeInfographic react component had a file name like this ExchangeInfographic.tsx
The json file containing json for the lottie animation had a file name like this exchangeInfographic.json
For some reason when the name of the json file and react component file was the same (except for capital letter for react component) after importing the component like this
import {ExchangeInfographic} from 'path to the file;'
It would return an object instead of function.
To fix it, I just changed the name of the file where json was to for example exchange.json
It's a kind of magic. It's a kind of maaagiiic...

How to use dynamic import with a named export in Next.js?

I have this react component. It works just fine for me.
import { Widget } from 'rasa-webchat';
function CustomWidget(){
return (
<Widget
initPayload={"payload"}
socketPath={"/socket.io/"}
customData={{"language": "en"}}
/>
)
}
export default CustomWidget;
But when I try to use it on my next.js website it fails to work.
It gives me a window is not defined error.
I think I resolved this particular error by using the dynamic importer:
import dynamic from "next/dynamic";
const webchat = dynamic(
() => {
return import('rasa-webchat');
},
{ ssr: false }
);
But now I can't figure out how to actually use the widget component from the package.
Am I allowed to import { Widget } from 'rasa-webchat' or is this just not compatible with next.js for some reason? If it's possible, how do I do it?
The syntax for named exports is slightly different. You can use the widget with a dynamic import as follows:
import dynamic from 'next/dynamic';
const Widget = dynamic(
() => import('rasa-webchat').then((mod) => mod.Widget),
{ ssr: false }
);
function CustomWidget(){
return (
<Widget
initPayload={"payload"}
socketPath={"/socket.io/"}
customData={{"language": "en"}}
/>
)
}
export default CustomWidget;
For further details check Next.js dynamic import documentation.
Nextjs is a frame work that allows you to build Static and Server Side rendered apps. So, it uses Nodesj under hood and window is not defined in nodejs. Only way to accessing window in react ssr frameworks is useEffect hook. Your dynamic import solution is right , becuase you are getting file on client side. I hope it makes sense.
Have a great day

TypeError: Object(...) is not a function when using react-toastify

I'm trying to get react-toastify to work in an app I'm writing while following an online course. I'm supposed to install a specific version but I always prefer using the very latest one but when I do, I'm getting a bunch of errors.
I've gone to the npm home page for React-Toastify and they provide very good documentation on how to use it and I believe I've followed the instructions from both the course and react-toastify correctly but I'm still getting an error.
I've defined react-toastify as the top of my App.js
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
and I'm simply calling a test toast as follows:
handleDelete = (post) => {
toast("deleted");
// toast.error("deleted");
}
and in my render method I have the <ToastContainer />:
render() {
return (
<React.Fragment>
<ToastContainer />
<button className="btn btn-error" onClick={this.handleDelete}>
Delete
</button>
When I click on my delete button I get an error (well I'm actually getting a bunch of them but this is the main one):
TypeError: Object(...) is not a function
useToastContainer
..myapp/node_modules/react-toastify/dist/react-toastify.esm.js:866
863 | }
864 |
865 | function useToastContainer(props) {
> 866 | var _useReducer = useReducer(function (x) {
867 | return x + 1;
868 | }, 0),
869 | forceUpdate = _useReducer[1];
Actually, I've just noticed that my <ToastContainer /> was commented out in my render method and the second I uncomment it, the same error occurs immediately as my page loads.
Am I missing something or is this a bug with react-notify and the version of React I'm using i.e. 16.4.1?
I was also facing a similar issue, this is because there are some conflicting dependencies with react-toastify in the newer versions with respect to its predecessor.
Also if you follow some courses they usually provide some resources to proceed with, when you start working on those resource and do a npm i for its dependencies it install certain versions of the package which is specified in the package.json file, so if you are trying to install a new package as a part of the course it might not be compatible with the ones mentioned in the resource files.
So to avoid conflict here you can manually install all the packages mentioned in package.json with the latest versions then install the latest version of react-toastify
OR
Try reverting the version of react-toastify to earlier version , maybe try with react-toastify#4.1 or the version mentioned in the course. (This worked for me)
install an older version of react-toastify and it will work just fine
Remove unused props.
handleDelete = () => {
toast("deleted");
// toast.error("deleted");
}
Or use the function props.
handleDelete = (post) => {
toast(post);
}
And call your function in arrow function.
render() {
return (
<React.Fragment>
<ToastContainer />
<button className="btn btn-error" onClick={() => {this.handleDelete('deleted')}}>
Delete
</button>
</React.Fragment>
)
What works for me was to create another file to hold the <ToastContainer/> and then import it in my App.js and it works fine. Here I'm giving you a simple example:
./src/toast.jsx
import React from "react";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
const Toast = () => {
const errorMessage = () => {
toast.error("Unexpected error occured");
};
return (
<div>
<button onClick={errorMessage} className="btn btn-primary">
Submit
</button>
<ToastContainer />
</div>
);
};
export default Toast;
./src/App.js
import React, { Component } from "react";
import "./App.css";
import Toast from "./toast";
class App extends Component {
state = {
};
render() {
return (
<React.Fragment>
//Your code...
<Toast />
</React.Fragment>
);
}
}
export default App;
However, my application is a little bit more complex and basically I have a file httpServices.js, where I'm using Axios library to make HTTP requests and catch errors. So if I catch an error while sending an Http request and I'm using "toast.error("Message")". I'm using the new file toast.jsx to hold a container for the errors and this container I import in my App.js.

Dynamically loading Material-UI Icons in React

I'm trying to make React component that dynamically imports requested Material-UI icon,
when the page loads. My solution presented here works, but it gives warning
at compile time. Additionally it slows down the compilation of the project.
Any idea on how to do this properly?
https://github.com/jurepetrovic/ordermanager_demo
The main logic is found in App.js, lines 5-10:
import React, { Component } from 'react';
import BarChartIcon from '#material-ui/icons/BarChart';
const MaterialIcon = ({ icon }) => {
console.log("icon: " + icon);
let resolved = require(`#material-ui/icons/${icon}`).default;
return React.createElement(resolved);
}
class App extends Component {
render() {
return (
<div>
<MaterialIcon icon={"PowerSettingsNew"} />
</div>
);
}
}
export default App;
The warning it gives is this:
Compile warning
I finally found the simplest solution to this problem:
import all material icons from the package:
import * as Icons from '#material-ui/icons'
I assume you fetch your icon names from your api and finally you have something like this:
var iconNamesArray = ["FitnessCenter","LocalDrink","Straighten"]
Finally load your Icons like below:
<div className="my-icons-wrapper-css">
{
iconNamesArray.map((el,ind)=>{
let DynamicIcon = Icons[el]
return(
<DynamicIcon className="my-icon-css"/>
);
})
}
</div>
And your icons will appear in the screen.

Adding Font Awesome Pro to React App - getting started

I'm trying to add Fontawesome pro to my react app.
I've tried almost all of the options on the getting started tab for Font Awesome - and all that is producing is the free brands. So - now I have a mash up of attempts and and currently stuck on following the instructions set out by clodal in this post
I have a package.json with the following dependencies:
"#fortawesome/fontawesome-svg-core": "^1.2.8",
"#fortawesome/pro-light-svg-icons": "^5.5.0",
"#fortawesome/free-solid-svg-icons": "^5.5.0",
"#fortawesome/pro-regular-svg-icons": "^5.5.0",
"#fortawesome/pro-solid-svg-icons": "^5.5.0",
"#fortawesome/react-fontawesome": "^0.1.3",
I have seen this post and note others are struggling to figure out how to get started with font awesome.
I have added global config auth token to my app.
I have read the upgrading instructions here.
Currently - i'm getting an error that says:
Error: Can't resolve '#fortawesome/pro-brands-svg-icons' in '/Users/18/src/routes/How/components/HowPage'
In that page, I have:
import React from 'react'
import PropTypes from 'prop-types'
import classes from './HowPage.scss'
import GridContainer from "components/Grid/GridContainer.jsx";
import GridItem from "components/Grid/GridItem.jsx";
import Clearfix from "components/Clearfix/Clearfix.jsx";
import { library } from '#fortawesome/fontawesome-svg-core'
import { fas } from '#fortawesome/pro-solid-svg-icons'
import { faTwitter } from '#fortawesome/pro-brands-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
export const HowPage = ({ how }) => (
<div className={classes.container}>
<h1 style={headstyle}>How it Works</h1>
<GridContainer justify="center">
<GridItem
xs={12}
sm={8}
md={8}
className={`${classes.mlAuto} ${classes.mrAuto} ${
classes.textCenter
}`}
>
<span>
<i className="fas fa-layer-plus"></i>
</span>
<i className="fal fa-stroopwafel"></i>
<FontAwesomeIcon icon="coffee" />
<i className="fab fa-twitter" />
</GridItem>
</GridContainer>
<pre>{JSON.stringify(how, null, 2)}</pre>
</div>
)
HowPage.propTypes = {
how: PropTypes.object // from enhancer (firestoreConnect + connect)
}
export default HowPage
In my index.html I have:
<link href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" rel="stylesheet">
I have tried adding these import statements to the page on which Im trying to use the fonts (I can't understand the library building instructions).
That produces the errors (expected, given the next issue):
I don't know where to add the following library add call:
library.add(fas, faTwitter)
My app gets initialised via main.js. That page has:
import React from 'react'
import ReactDOM from 'react-dom'
import createStore from './store/createStore'
import { initScripts } from 'utils'
import { version } from '../package.json'
import { env } from './config'
import './styles/core.scss'
// import { library } from '#fortawesome/fontawesome-svg-core'
// import { fal } from '#fortawesome/pro-light-svg-icons'
// Window Variables
// ------------------------------------
window.version = version
window.env = env
initScripts()
// Store Initialization
// ------------------------------------
const initialState = window.___INITIAL_STATE__ || {
firebase: { authError: null }
}
const store = createStore(initialState)
// Render Setup
// ------------------------------------
const MOUNT_NODE = document.getElementById('root')
let render = () => {
const App = require('./containers/App').default
const routes = require('./routes/index').default(store)
ReactDOM.render(<App store={store} routes={routes} />, MOUNT_NODE)
}
// Development Tools
// ------------------------------------
if (__DEV__) {
if (module.hot) {
const renderApp = render
const renderError = error => {
const RedBox = require('redbox-react').default
ReactDOM.render(<RedBox error={error} />, MOUNT_NODE)
}
render = () => {
try {
renderApp()
} catch (e) {
console.error(e) // eslint-disable-line no-console
renderError(e)
}
}
// Setup hot module replacement
module.hot.accept(['./containers/App', './routes/index'], () =>
setImmediate(() => {
ReactDOM.unmountComponentAtNode(MOUNT_NODE)
render()
})
)
}
}
// Let's Go!
// ------------------------------------
if (!__TEST__) render()
I think the instructions want me to write that library add call in there - but I can't understand how to do it.
I have seen this post - this user has figured out how to add code to the app.js file. I think I am stuck on this step. My app.js is in main.js - I don't know where to put the library call and I don't know whether this example means that the user will only have access to the 2 icons named in that post (faSpinnerThird, faCircle).
I am using Material-UI - and can see that it contemplates the use of font awesome icons. I just can't figure out how to set it up.
PS: the contributing guidelines on the GitHub support page ask for questions to be tagged with react-fontawesome. There isn't a tag for that reference - I don't have enough points to create one - maybe someone who does can sort that out.
For others struggling with FA in React - PKK's answer on this post helped me How to integrate FontAwesome 5 Pro with React?
However, it doesn't seem to work with 2 word icon names. But - at least it works for many icons. I always thought of FA as plug and play - this has been many hours in figuring out how to get it to work.
According to the "importing icons" documentation, there is no #fortawesome/pro-brands-svg-icons. There is only #fortawesome/free-brands-svg-icons.

Resources