ReactJS- Directory selection dialog not working - javascript

I want a directory selection dialog in my React App. I followed this SO thread that might work for some people but not for me.
Getting compile time error as
Property 'directory' does not exist on type 'DetailedHTMLProps<InputHTMLAttributes, HTMLInputElement>'.
I upgraded react to the latest RC-version 17.rc.1 thinking that there may be a bug fix for this but no success.
Edit
There is a hack to add this script at the end of file using tag for directory selection, suggested by #Scratch'N'Purr in comments.
declare module 'react' {
interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
// extends React's HTMLAttributes
directory?: string;
webkitdirectory?:string;
}
}

It works fine in Javascript but the problem is with Typescript. Guess, you are right about it being an issue.
You can set it manually using ref though.
import * as React from "react";
import "./styles.css";
export default function App() {
const ref = React.useRef<HTMLInputElement>(null);
React.useEffect(() => {
if (ref.current !== null) {
ref.current.setAttribute("directory", "");
ref.current.setAttribute("webkitdirectory", "");
}
}, [ref]);
return <input type="file" ref={ref} />;
}

Related

The final argument passed to useEffect changed size between renders in Next.js Typescript

import dynamic from "next/dynamic"
import React, { ReactNode } from "react";
type ButtonProps = {
type: string,
children: ReactNode,
onClick: () => void
}
const ButtonWrapper: React.ComponentType<{}> = dynamic(() => import('element-react').then((res: any) => { return res.Button }), { ssr: false})
export const Button: React.FC<ButtonProps> = (ButtonProps) => {
return <><ButtonWrapper {...ButtonProps}></ButtonWrapper></>
}
I tried to implement Element-React UI to my next.js project, and I got this warning, and I want to solve it. I didn't warn when I comment this component code.
Does anyone know how to solve this warning?
The problem is in some useEffect. React detected that dependency array has changed size. To fix it you need to find that useEffect and figure out why this is happening. Check error message to find a stacktrace to the component that causes error.
This seems like the error is inside the library component. In this case you need to check if it's misused or perhaps it's a bug in a library. Try searching github issues of the project.

React JS, props validation

New to React JS, props validation practise as follows:
import React from 'react';
import PropTypes from 'prop-types';
class App extends React.Component {
render() {
return (
<div>
<h3>String : {this.props.propstring}</h3>
</div>
);
}
}
App.propTypes = {
propstring : PropTypes.string
}
App.defaultProps = {
propstring : "My Name"
}
export default App;
import React, { component } from 'react';
import ReactDOM from 'react-dom';
import App from './AppProp.js';
ReactDOM.render(<App />,document.getElementById('root'));
Getting an error as:
TypeError: Class extends value undefined is not a constructor or null.
What am I missing here and how can I resolve the above error?
There are 2 possible problems. Most probably you're importing { component }(like you do in your index file, which is wrong), instead of { Component } somewhere in your code and trying to extend component which doesn't exist.
The other reason is that you might be circularly importing classes, but I doubt it. Also, is your file called AppProp.js?
Post the stack trace and it would also help if you post all the components you're using. Post your package.json as well, as you might be using wrong absolute paths.
The code is perfectly fine. I executed it on my local machine and it ran fine.
The only issue you may be facing is to with
circularly importing classes, which is apparently a limitation
Know more from the resource:
https://esdiscuss.org/topic/how-to-solve-this-basic-es6-module-circular-dependency-problem

Material UI component `theme.spacing` not defined once built

I am building a Material-UI text editor using draft.js and wrapping all the functionality in Material-UI components.
I've gotten comfortable using ~3.9 but for this project decided to update to 4.0. Maybe I'm missing something here but this usually works for me with no issues
const styles = theme => ({
paper: {
paddingBottom: theme.spacing(2)
},
...
})
import { withStyles } from "#material-ui/styles"
...
export class EditorComponent extends Component {
...
render() {
const { classes } = this.props
}
}
export default withStyles(styles, { withTheme: true })(EditorComponent)
This works while running in a webpack-dev-server but when I build to javascript and attempt to import it into another project and use it I get this error in the console...
Uncaught TypeError: theme.spacing is not a function
I can't seem to find anything relevant googling this issue.
Here is the repo if looking at my build script would help
https://github.com/jrdn91/material-ui-rte
Turns out that pulling in withStyles or makeStyles etc. from #material-ui/styles does not include the default theme. There are wrapped version of these included in #material-ui/core/styles which do include the default theme.
So changing from import { withStyles } from "#material-ui/styles" to import { withStyles } from "#material-ui/core/styles" will fix this issue.
Referenced from this page
https://material-ui.com/customization/default-theme/#material-ui-core-styles-vs-material-ui-styles

Only dynamically import module once rather than on every component instance in React

I have a react component that conditionally imports a module. The reason is if the module is imported normally at the top of the file, this breaks another project's webpack build that depends on this component because it cannot process the imported module.
I have solved this issue with es6 dynamic imports - however, the problem now is that every instance of the component re-imports the module. If I have 100 components on 1 page, it'll import that module 100 times, making it horribly inefficient and slowing page load times.
What would be the proper way to only import it once, then have the rest of all component instances reference that 1 dynamically imported module?
Here's my component:
import React from "react"
export default class Link extends React.Component {
state = {
gatsbyLink: null
}
...
componentDidMount() {
if (GLOBAL_FLAG) {
import("gatsby").then(({ Link }) => {
this.setState({
gatsbyLink: Link
})
})
}
}
render() {
const { gatsbyLink } = this.state;
const GatsbyLink = gatsbyLink ? gatsbyLink : "";
...
return (<GatsbyLink {...}>...</GatsbyLink>)
}
}
I'm not sure dynamically imported modules are cached. If they aren't you could export a promise that resolves a dynamically imported gatsby if the flag is set.
You will still have to import and call it in every component where you use gatsby, but it will not dynamically import the module every time.
const conditionallyResolveGatsby = () => {
// You could reject as well
return GLOBAL_FLAG ? import('gatsby') : Promise.resolve();
};
export default conditionallyResolveGatsby();
You could also try to use require.

How to import node module in React-Kotlin?

I created an app using the create-react-kotlin-app command and it loads in Chrome fine. I added the React Material UI package via NPM and that was successful. Now how do I use the Material UI module in my component?
Normally with JavaScript, it's a simple import Button from '#material-ui/core/Button' at the top of the component's file, but Kotlin doesn't like that.
How do I translate that line to Kotlin? I am not using Gradle.
I have been struggling with this problem for days now. I came up with the following solution. First we will see multiple ways to declare external modules, then I will show how to use them
.
Consider the following javascript code
import Button from '#material-ui/core/Button' // this means button is exported as default
This will be imported in kotlin in the following ways
Button.kt
#file:JsModule("#material-ui/core/Button")
#file:JsNonModule
package com.mypckage.mykillerapp
import react.Component
import react.RProps
import react.RState
import react.ReactElement
#JsName("default") // because it was exported as default
external val Button : RClass<RProps>
// way 2
#JsName("default")
external class Button : Component<RProps,RState> {
override fun render(): ReactElement?
}
But again, if the statement intend for kotlin has to match the javascript import statement bellow,
import { Button } from "material-ui" // not exported as default
We use the following approach: Button.kt
#file:JsModule("material-ui")
#file:JsNonModule
package com.mypckage.mykillerapp
import react.Component
import react.RProps
import react.RState
import react.ReactElement
// way 1
#JsName("Button") // because it was exported as default
external val Button : RClass<RProps>
// way 2
#JsName("Button")
external class Button : Component<RProps,RState> {
override fun render(): ReactElement?
}
once you have declared on how to use your components, you can just use them as follows:
//way 1:
fun RBuilder.render() {
div {
Button {
attrs.asDynamic().className="submit-button"
+"Submit"
}
}
}
//way 2:
fun RBuilder.render() {
div {
child(Button::class) {
attrs.asDynamic().className="submit-button"
+"Submit"
}
}
}
great. you have imported your component. But until then your are not relying on kotlin type safety and even code completion, to achieve that, you have to go to extra length
as shown bellow
external interface ButtonProps: RProps {
var className : String
var onClick: (Event?)->Unit
var color: String
// . . .
var href: String
}
then go ahead and declare your button as
#JsModule("#material-ui/core/Button")
#JsNonModule
#JsName("default") // because it was exported as default
external val Button : RClass<ButtonProps>
and you can now use it with type safety and code completion as shown bellow
fun RBuilder.render() {
div {
Button {
attrs {
className = "submit-button"
onClick = {
window.alert("Vois La")
}
}
+"Submit"
}
}
}
Hope this helps. Happy coding
EDIT:
There is a community wrapper for material-ui components here
HINT:
Use way 1, as you can see, it is less verbose
The Kotlin way for importing dependencies is close to standard JS importing:
import React from 'react';
export function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Based on Creating a simple React component with Kotlin.
package hello
import react.*
import react.dom.*
fun RBuilder.hello(name: String) {
h1 {
+"Hello, $name"
}
}
Usually (as Kotlin is Java-based) it uses Gradle tool to handle dependencies:
// part of build.gradle
kotlinFrontend {
// ...
npm {
// ...
dependency("react")
dependency("react-dom")
dependency("react-router")
dependency("react-markdown")
devDependency("css-loader")
devDependency("babel-core")
// ...
}
And are referenced like above:
HomeView.kt:
// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/HomeView.kt
import kotlinx.html.*
import org.jetbrains.demo.thinkter.model.*
import react.*
import react.dom.*
import kotlinx.coroutines.experimental.launch
ReactMarkdown.kt:
// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/ReactMarkdown.kt
package org.jetbrains.demo.thinkter
import react.*
private val ReactMarkdown: dynamic = runtime.wrappers.require("react-markdown")
Based on: kotlin-fullstack-sample
In create-react-kotlin-app additionally faced the possibility of importing with #JsModule() annotation, while dependencies managing is handled in standard way via package.json:
// src/logo/Logo.kt (outcome of creating new app)
package logo
import react.*
import react.dom.*
import kotlinext.js.*
import kotlinx.html.style
#JsModule("src/logo/react.svg")
external val reactLogo: dynamic
#JsModule("src/logo/kotlin.svg")
external val kotlinLogo: dynamic
And can be also successfully used for JS libraries importing.
Another way would be to use kotlinext.js.*:
// index/index.kt
import kotlinext.js.*
fun main(args: Array<String>) {
requireAll(require.context("src", true, js("/\\.css$/")))
// ...
}
Which provides also require(module: String) function.

Categories

Resources