How to import Lottie component? - import

Remix is prone to the following error when using import on top-level components TypeError: Cannot read properties of undefined (reading 'root').
So I've done as they recommend and have the following imports.server.tsx file.
export * from "lottie-react";
Then my component app.tsx looks exactly like this lottie example.
import React from "react";
import * as Lottie from "../imports.server";
import groovyWalkAnimation from "../../public/assets/102875-cinema-clap.json";
export default function App() {
return (
<>
<h1>lottie-react - Component</h1>
<Lottie animationData={groovyWalkAnimation} />;
</>
);
}
but I get the following error
JSX element type 'Lottie' does not have any construct or call
signatures.ts(2604)
Edit 1:
The following seems to have worked for imports:
imports.server.tsx
import Lottie from "lottie-react";
export default Lottie;
AppTry.tsx
import React from "react";
import Lottie from "../imports.server";
import groovyWalkAnimation from "../../public/assets/102875-cinema-clap.json";
export default function AppTry() {
// console.log(LottieModule);
return (
<>
<h1>lottie-react - Component</h1>
<Lottie animationData={groovyWalkAnimation}></Lottie>
</>
);
}
Now the various paramaters like "animationData" and "autoPlay" pop up on the Lottie component which I assume means the import is working? However I am now getting this error when rendering AppTry.tsx?
react.development.js:220 Warning: React.createElement: type is invalid
-- expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to
export your component from the file it's defined in, or you might have
mixed up default and named imports.
Check the render method of AppTry.
Edit 2:
import { useLottie } from "lottie-react";
import Lottie from "lottie-react";
import groovyWalkAnimation from "../../public/assets/102875-cinema-clap.json";
const Example = () => {
const options = {
animationData: groovyWalkAnimation,
loop: true,
autoplay: true,
};
const { View } = useLottie(options);
return View;
};
const Example1 = () => {
return <Lottie animationData={groovyWalkAnimation} />;
};
export const TopicOverview = () => {
return (
<div className="space-y-20">
<Example1></Example1>
<Example></Example>
</div>
);
};

Looks like it has to do with your way of importing Lottie.
Shouldn't you import Lottie like this?:
import Lottie from "lottie-react";

I also struggled to get this working in Remix.
You can do the lazy load import somewhere higher up in the tree too.
import type { LottiePlayer } from "#lottiefiles/lottie-player";
import { useEffect } from "react";
interface LottieCompProps {
src: LottiePlayer["src"];
style?: Partial<LottiePlayer["style"]>;
}
function LottieComp({ src, style = {} }: LottieCompProps): JSX.Element | null {
// NB: otherwise, will cause app to crash. see https://remix.run/docs/en/v1/guides/constraints#third-party-module-side-effects
useEffect(() => {
import("#lottiefiles/lottie-player");
},[]);
if (typeof document === "undefined") return null;
return (
//#ts-expect-error dynamic import
<lottie-player
autoplay
loop
mode="normal"
src={typeof src === "string" ? src : JSON.stringify(src)}
style={{
...{
width: "100%",
backgroundColor: "transparent",
},
...style,
}}
/>
);
}
export default LottieComp;

The issue was in my root.tsx, an ErrorBoundary() function that called an <UnexpectedErrors/> component.
This same component was being called in various slug.tsx files. For some reason remix did not like this.
Having two different <UnexpectedErrors/> and <UnexpectedErrors2/> components - one for the slug.tsx files and one for the index.tsx files fixed this.

Related

How to search by data-test? (not data-testid)

When I import screen object like this
import { render, screen } from '#testing-library/react';
it allows me to issue the following command: screen.findByTestId(...), but how can I search by data-test (not data-testid)? Tried to search by custom attribute, but there was no findByAttribute method in screen either.
Have you had a chance to see the the document?
https://testing-library.com/docs/dom-testing-library/api-custom-queries/
If you want to query with your own-defined attribute, you can make one using buildQueries
// custom-queries.js
import {queryHelpers, buildQueries} from '#testing-library/react'
// query
const queryAllByData = (...args) =>
queryHelpers.queryAllByAttribute('data-test', ...args)
const [
queryByDataTest,
] = buildQueries(queryAllByData)
export {
queryByDataTest
}
// test-utils.js
import {render, queries} from '#testing-library/react'
import * as customQueries from './custom-queries'
const customRender = (ui, options) =>
render(ui, {queries: {...queries, ...customQueries}, ...options})
// re-export everything
export * from '#testing-library/react'
// override render method
export {customRender as render}
//test.spec.jsx
const {getByData} = render(<Component />)
expect(getByData('my-component')).toHaveTextContent('Hello')
You can find more in the attached document.

Ionic-React: Not able to customize single IonSelectOption with CSS class

I'm trying to customize a single IonSelectOption with a custom CSS class to change the color of one IonSelectOption. I am copy-pasting the code from Ionic's documentation but it still isn't working. The CSS className that I provide to the IonSelectOption does not seem to get passed along to whatever interface that it selected. Hope someone can help me out!
Link to Documentation. This is the code I'm using:
import React from 'react';
import { IonContent, IonItem, IonLabel, IonSelect, IonSelectOption, IonPage } from '#ionic/react';
const options = {
cssClass: 'my-custom-interface'
};
export const SelectOptionExample: React.FC = () => {
return (
<IonPage>
<IonContent>
<IonItem>
<IonLabel>Select</IonLabel>
<IonSelect interface="popover" interfaceOptions={options}>
<IonSelectOption value="brown" class="brown-option">Brown</IonSelectOption>
<IonSelectOption value="blonde">Blonde</IonSelectOption>
<IonSelectOption value="black">Black</IonSelectOption>
<IonSelectOption value="red">Red</IonSelectOption>
</IonSelect>
</IonItem>
</IonContent>
</IonPage>
);
};
and the CSS:
/* Popover Interface: set color for the popover using Item's CSS variables */
.my-custom-interface .brown-option {
--color: #5e3e2c;
--color-hover: #362419;
}
in react, it is className, not class

breakpoints with {withStyles} from '#material-ui /styles'

I am trying to use breakpoints with {withStyles} from "#material-ui/styles", but the debugger shows that theme.breakpoints is not defined.
I tried to wrap the component with ThemeProvider but it does not work.
https://codesandbox.io/s/material-demo-shgh7?from-embed
withStyles exported with #material-ui/styles not provide theme props, you'll use import { withStyles } from "#material-ui/core/styles";
Exemplo no code sand box arrumado ai
class app extends Component{
render(){
const {classes} = this.props
return (
<div className={classes.root}></div>
)
}
}
const style = theme => ({
root: {
[theme.breakpoints.up('sm'){ //only show on mobile or small screen
display: 'none'
},
}
})
export default withStyles(style)(app)

How to disable the SaveButton when the SimpleForm is invalid in a react-admin app?

In a react-admin SimpleForm component validation is working fine when I click the save button. The field that is required is highlighted and marked red when I click the save button.
I'd like to add a className to the SaveButton as long as the form is invalid. This way I can make it clear to the user that he's not done with the form yet and prevent the user from clicking it.
This is a simplified version of such a SimpleForm.
import {
required,
//...
} from 'react-admin';
const UserCreateToolbar = props =>
<Toolbar {...props}>
<SaveButton
label="user.action.save_and_show"
redirect="show"
submitOnEnter={true}
/>
</Toolbar>;
export const UserCreate = props =>
<Create {...props}>
<SimpleForm
toolbar={<UserCreateToolbar />}
>
<TextInput source="name" validate={[required()]} />
</SimpleForm>
</Create>;
You can create your own SaveButton component, connected to redux, which will get the validation status from the state (check the redux-form documentation) for the form which is always named record-form in react-admin.
Then, you can apply the disabled prop on the button and eventually tweak its styles
Here's my own SaveButton component I came up with. It's working for me. Thanks #Gildas for pointing me in the right direction.
import React from 'react';
import PropTypes from 'prop-types';
import { reduxForm } from 'redux-form';
import { SaveButton } from 'react-admin';
const SaveButtonAware = ({ invalid, ...rest }) => (
<SaveButton disabled={invalid} {...rest} />
);
SaveButtonAware.propTypes = {
invalid: PropTypes.bool,
};
export default reduxForm({
form: 'record-form',
})(SaveButtonAware);
Update. Apparently, this is working too. Not sure why.
import React from 'react';
import PropTypes from 'prop-types';
import { SaveButton } from 'react-admin';
const SaveButtonAware = ({ invalid, ...rest }) => (
<SaveButton disabled={invalid} {...rest} />
);
SaveButtonAware.propTypes = {
invalid: PropTypes.bool,
};
export default SaveButtonAware;
You should first create a customized toolbar and set Save button's disabled element to Toolbars invalid state, as shown below. ( Toolbar always have the state of form)
import * as React from "react";
import {
Toolbar,
SaveButton
} from 'react-admin';
const CustomToolbar = (props) => (
<Toolbar {...props}>
<SaveButton disabled={props.invalid}/>
</Toolbar>
);
export default CustomToolbar;
Then use this customized toolbar in your form like shown below:
<SimpleForm redirect="list" toolbar={<CustomToolbar/>}>
{your form elements}
</SimpleForm>

Support for a permanent clipped AppDrawer

I'm trying to make a permanent clipped navigation drawer with Material UI as per https://material.io/guidelines/patterns/navigation-drawer.html
Seems that there is a pull request out for this but not yet merged: https://github.com/callemall/material-ui/pull/6878
At this stage I'm trying to override with styles but can not get my left nav (paper) to apply the style marginTop: '50px',
Are there some samples out there on how to achieve this with v1.0.0-alpha.21?
They changed the way you have to override certain styles in v1. The inline styles no longer work. Certain parts of a component can be overridden with a simple className applied to the component. See this link for further details https://material-ui-1dab0.firebaseapp.com/customization/overrides.
Some deeper nested properties of certain components i.e the height of the Drawer can only be accessed by overriding the class itself. In this case the paper class of the drawer element.
This is a simple example
import React, { Component } from "react";
import Drawer from "material-ui/Drawer";
import { withStyles, createStyleSheet } from "material-ui/styles";
import PropTypes from 'prop-types';
const styleSheet = createStyleSheet("SideNav", {
paper: {
marginTop: '50px'
}
});
class SideNav extends Component {
....
render() {
return (
<Drawer
classes={{paper: this.props.classes.paper}}
docked={true}
>
....
</Drawer>
);
}
}
SideNav.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styleSheet)(SideNav);