React createElement type is invalid - reactjs

I am having trouble trying to publish a node module, material-ui-next-datepicker
It is working locally but not when installed as a node module
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import {MuiThemeProvider, createMuiTheme, withStyles, StyledComponentProps, Theme} from 'material-ui/styles'
import DateFormatInput from 'material-ui-next-datepicker'
const theme = createMuiTheme()
const styles = (theme:Theme):Record<string, React.CSSProperties> => ({
container: {
width: '100vw',
height: '100vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}
})
#(withStyles as any)(styles)
class DemoPage extends React.Component<DemoPageProps, DemoPageState> {
constructor(props) {
super(props)
this.state = {
date: undefined
}
}
onChange = (date:Date) => {
console.log(date)
this.setState({date})
}
render() {
const {classes} = this.props
const {date} = this.state
return (
<div className={classes.container}>
<DateFormatInput name='date-input' value={date} onChange={this.onChange} label='Date'/>
</div>
)
}
}
interface DemoPageProps extends React.Props<{}>, StyledComponentProps {
}
interface DemoPageState {
date: Date
}
ReactDOM.render(
<MuiThemeProvider theme={theme}>
<DemoPage/>
</MuiThemeProvider>
, document.getElementById('root'))
Here's the error in the browser
When I do print out DateFormatInput, it looks fine...definitely not undefined
I am not too familiar with dependencies and how to differentiate between peer, ambient or bundled. So, I do need some help in making this node module work

Finally able to solve this issue simply by adding .npmignore
I removed all my demo files like:
demo/
src/
index.html
tsconfig.json
webpack.config.js
Then it starts working fine by importing...

Related

Styles not applied at child component with Emotion 11 css prop in Gatsby and Typescript project

I'am using Emotion CSS prop to style my Gatsby / Typescript application.
I am using Gatsby 2 and Emotion 11.
In e.g. my Header component I render a Logo component:
/** #jsx jsx */
import { FC } from 'react';
import { jsx } from '#emotion/react';
import Logo from 'components/Logo';
import useSiteMetaData from 'hooks/useSiteMetadata';
import Styles from './Header.styles';
import { Props } from './Header.types';
const Header: FC<Props> = () => {
const styles = Styles();
const { title } = useSiteMetaData();
return (
<header css={styles.root}>
<Logo siteTitle={title} css={styles.logo} />
</header>
);
};
export default Header;
But on the css prop of my child component I get a Typescript error:
Property 'css' does not exist on type 'IntrinsicAttributes &
Props'.ts(2322)
I added below to tsconfig.json and that solves the linting error:
{
"compilerOptions": {
"types": ["#emotion/react/types/css-prop"],
}
}
But somehow the styles are not applied from within my Header.styles.ts, so I am able to overwrite/add some styles of my child component (Logo)?
You have such example in css-prop docs.
The P component acts like your Logo component, and ArticleText is your Header
const P = props => (
<p
css={{
margin: 0,
fontSize: 12,
lineHeight: '1.5',
fontFamily: 'sans-serif',
color: 'black'
}}
{...props} // <- props contains the `className` prop
/>
)
const ArticleText = props => (
<P
css={{
fontSize: 14,
fontFamily: 'Georgia, serif',
color: 'darkgray'
}}
{...props} // <- props contains the `className` prop
/>
)
You mean need to pass the className prop, see related answer.

React Native Algolia Instant Search & SearchBox

When following the Algolia docs (https://www.algolia.com/doc/api-reference/widgets/react/) to setup a simple search of the Alogila index with the following code
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {Text, View, StyleSheet, Button, TextInput} from 'react-native';
import algoliasearch from 'algoliasearch/lite';
import { InstantSearch, Index, SearchBox, Hits } from 'react-instantsearch-dom';
const searchClient = algoliasearch(
'**********', //app ID
'************************' //app key
);
class MyApp extends Component {
constructor(props){
super(props);
}
render(){
return (
<View style={{
flex: 1,
alignItems: "center",
flexDirection: "column",
paddingTop: 20
}}>
<InstantSearch
searchClient={searchClient}
indexName="dev_INVENTORY">
<SearchBox/>
</InstantSearch>
</View>
)}
};
const styles = StyleSheet.create({});
export default MyApp;
I get the error 'Invariant Violation: View config not found for name input. Make sure to start component names with a capital letter.
This error is located at in input (created by Searchbox)....'
When I remove the SearchBox code the app functions fine but as soon as I add it i come across the error, but clearly all the elements are capitalized correctly (unless i've made a ridiculous silly oversight!?)
I wondered if the error was related to this persons issue;
Using Algolia react-instantsearch with react-native but i dont think it is.
If anyone has any suggestions just so I can get started with searching Algolia that would be ace as I'm a bit stuck!
The issue is that you're trying to use some widgets from react-instantsearch-dom which are not compatible with React Native.
For React Native you'll need to use the connectors instead of the widgets: https://www.algolia.com/doc/guides/building-search-ui/going-further/native/react/#using-connectors-instead-of-widgets
In your case it should give you something like:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, StyleSheet, TextInput } from 'react-native';
import algoliasearch from 'algoliasearch/lite';
import { InstantSearch, connectSearchBox } from 'react-instantsearch-native';
const searchClient = algoliasearch(
'**********', // app ID
'************************' // app key
);
class SearchBox extends Component {
render() {
return (
<View>
<TextInput
onChangeText={text => this.props.refine(text)}
value={this.props.currentRefinement}
placeholder={'Search a product...'}
clearButtonMode={'always'}
spellCheck={false}
autoCorrect={false}
autoCapitalize={'none'}
/>
</View>
);
}
}
SearchBox.propTypes = {
refine: PropTypes.func.isRequired,
currentRefinement: PropTypes.string,
};
const ConnectedSearchBox = connectSearchBox(SearchBox);
class MyApp extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View
style={{
flex: 1,
alignItems: 'center',
flexDirection: 'column',
paddingTop: 20,
}}
>
<InstantSearch searchClient={searchClient} indexName="dev_INVENTORY">
<ConnectedSearchBox />
</InstantSearch>
</View>
);
}
}
const styles = StyleSheet.create({});
export default MyApp;

Invalid hook call. Hooks can only be called inside of the body of a function component when apply style to class base component with material-ui

I am just started to learn reactjs using material-ui but getting this error when apply style to my component. My code:
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}));
class NavMenu extends React.Component {
constructor(props) {
super(props);
this.state = {
isOpen: false
};
}
render() {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="Menu"
>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
className={classes.title}
>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
}
export default NavMenu;
and this is Error:
material-ui makeStyles function only works inside function components, as it uses the new React Hooks APIs inside.
You have two options:
Convert your class component to a functional component.
Use a Higher Order Component as in material-ui docs
I personally recommend the first approach, as this is becoming the new standard in React development.
This tutorial may help you get started with functional components
and check the docs for React Hooks
Use withStyles:
App.js:
import {withStyles} from '#material-ui/core/styles'
// ...
const styles = theme => ({
paper: {
padding: theme.spacing(2),
// ...
},
// ...
})
class App extends React.Component {
render() {
const {classes} = this.props
// ...
}
}
export default withStyles(styles)(App)
Root.js:
import React, {Component} from 'react'
import App from './App'
import {ThemeProvider} from '#material-ui/styles'
import theme from '../theme'
export default class Root extends Component {
render() {
return (
<ThemeProvider theme={theme}>
<App/>
</ThemeProvider>
)
}
}
theme.js:
import {createMuiTheme} from '#material-ui/core/styles'
const theme = createMuiTheme({
palette: {
primary: ...
secondary: ...
},
// ...
}
export default theme
See Theming - Material-UI.
See Higher-order component API.
if you have created a functional component and still run into this issue... the next thing to look for are the dependency versions.
I tried a new stackblitz project to test a material-ui component and got this error. My dependencies were:
react 16.12
react-dom 16.12
#material-ui/core 4.9.14
So I had to change to latest react version using react#latest and react-dom#latest which got me to the following:
react 16.13.1
react-dom 16.13.1
#material-ui/core 4.9.14
Sharing here so that it can help other people who run into this... thanks to this post for the hint

Material-UI withStyles not adding classes to props

I'm trying to implement some styling using Material-UI's withStyles method, however I'm not able to get classes as a prop. Any suggestions as to what I'm missing? I've included the relevant code below, but note that there is an <App> component in this file that I'm leaving out for brevity.
import React from 'react'
import ReactDOM from "react-dom";
import {Paper, Typography} from '#material-ui/core'
import {withStyles} from '#material-ui/core/styles'
import NavBar from "./navBar";
class Recipe extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('Recipe Did Mount')
}
render() {
const {recipeData, classes} = this.props;
return (
<Paper>
<Typography className={classes.recipeName}>{recipeData.name}</Typography>
<Typography className={classes.recipeIngredients}>{recipeData.ingredients}</Typography>
<Typography className={classes.recipeInstructions}>{recipeData.instructions}</Typography>
</Paper>
)
}
}
const styles = {
root: {
fontSize: "1.0rem",
margin: "0px"
},
recipeName: {
fontSize: "1.0rem",
margin: "0px"
},
recipeIngredients: {
fontSize: "1.0rem",
margin: "0px" },
recipeInstructions: {
fontSize: "1.0rem",
margin: "0px" }
};
withStyles(styles)(Recipe);
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<App/>,
document.body.appendChild(document.createElement('div')),
)
});
Since you aren't setting withStyles(styles)(Recipe); into a variable, I suspect you must be using Recipe directly within App.
withStyles doesn't change Recipe. withStyles creates a new component that wraps Recipe and passes the classes prop to it. In order to see the classes prop, you need to use the newly-created component with something like the following:
const StyledRecipe = withStyles(styles)(Recipe);
const App = ()=> {
return <StyledRecipe/>;
}
Assuming App is defined in a separate file (for others who may come looking for this question), change the
`withStyles(styles)(Recipe);`
To
export default withStyles(styles)(Recipe);
As Ryan already explained ' withStyles is the higher order component that creates and returns a new component'

Embed Typeform in React app

How can I embed a Typeform form in my React app?
The embed code that Typeform provide doesn't compile in JSX.
This is a sample of the embed code:
<div class="typeform-widget" data-url="https://sample.typeform.com/to/32423" style="width: 100%; height: 500px;"></div> <script> (function() { var qs,js,q,s,d=document, gi=d.getElementById, ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm", b="https://embed.typeform.com/"; if(!gi.call(d,id)) { js=ce.call(d,"script"); js.id=id; js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })() </script> <div style="font-family: Sans-Serif;font-size: 12px;color: #999;opacity: 0.5; padding-top: 5px;"> powered by Typeform </div>
You can use a React wrapper component I created: https://github.com/alexgarces/react-typeform-embed
It uses the official Typeform Embed SDK under the hood. Basically you have to pass your form url, but it also supports other SDK options.
import React from 'react';
import { ReactTypeformEmbed } from 'react-typeform-embed';
class App extends React.Component {
render() {
return <ReactTypeformEmbed url="https://demo.typeform.com/to/njdbt5" />;
}
}
You can view Typeform documentation for embedding with JavaScript here.
And their official npm module here.
Use React refs to trigger initialisation similarly to how you would initialise a jQuery plugin for instance.
import React from 'react';
import * as typeformEmbed from '#typeform/embed'
class Form extends React.Component {
constructor(props) {
super(props);
this.el = null;
}
componentDidMount() {
if (this.el) {
typeformEmbed.makeWidget(this.el, "https://sample.typeform.com/to/32423", {
hideFooter: true,
hideHeaders: true,
opacity: 0
});
}
}
render() {
return (
<div ref={(el) => this.el = el} style={{width: '100%', height: '300px'}} />
)
}
}
export default Form;
Inspired by Elise Chant's solution and using function based components, hooks and Typescript, this is what I come up with for my project. I did not want to install another thin wrapper on top of the official SDK.
import * as typeformEmbed from '#typeform/embed';
import React, { useEffect, useRef } from 'react';
interface EmbeddedTypeformProps {
link: string;
hideFooter?: boolean;
hideHeaders?: boolean;
opacity?: number;
}
export const EmbeddedTypeform: React.FunctionComponent<EmbeddedTypeformProps> = ({
link,
hideFooter = true,
hideHeaders = true,
opacity = 90,
}) => {
const elementRef = useRef(null);
useEffect(() => {
typeformEmbed.makeWidget(elementRef.current, link, {
hideFooter,
hideHeaders,
opacity,
});
}, [link]);
return (
<div
ref={elementRef}
style={{ width: '100%', height: '100%', flex: '1 1 auto' }}
/>
);
};
If you are using Typescript with react and you got this error just make sure that noImplicitAny set to false in tsconfig file :
"noImplicitAny": false,

Resources