I am trying to use rich-markdown-editor to get values but the method am using is not modular. Can someone suggest a better way. I have tried both onChange and onSave but cannot seem to get them to work.According to their documentation
onSave({ done: boolean }): void
This callback is triggered when the user explicitly requests to save using a keyboard shortcut, Cmd+S or Cmd+Enter. You can use this as a signal to save the document to a remote server.
onChange(() => value): void
This callback is triggered when the contents of the editor changes, usually due to user input such as a keystroke or using formatting options. You may use this to locally persist the editors state.
import React, { useState } from "react";
import Editor from "rich-markdown-editor";
const Whiteboard = () => {
const [content, setContent] = useState("");
return (
<div>
<div>
<h1>Your Content</h1>
<Editor id="123" value={content} onChange={setContent} />
</div>
{content}
</div>
);
};
export default Whiteboard;
Try
<Editor id="123" value={content} onChange={(value) => setContent(value()} />
Related
I am new to react. A task assigned to create drag and drop component. I followed some blogs to do the task, which only accept image file types. Now the task is when clicked on the upload icon it should open file explorer which should only show image type files. I cannot try to figure out how that would work. Part of my codes which i took from various blogs are:
Drag and drop component:
import React from "react";
import { useDropzone } from "react-dropzone";
import UploadIcon from '#mui/icons-material/Upload';
const Dropzone = ({ onDrop, accept }) => {
// Initializing useDropzone hooks with options
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accept
});
/*
useDropzone hooks exposes two functions called getRootProps and getInputProps
and also exposes isDragActive boolean
*/
return (
<div className="dropzone-div" {...getRootProps()}>
<input className="dropzone-input" {...getInputProps()} accept=".gif,.jpg,.jpeg,.png"/>
<div className="text-center">
<UploadIcon fontSize="large"/>
{isDragActive ? (
<p className="dropzone-content"> Release to drop the files here</p>
) : (
<p className="dropzone-content">
<b> Choose a file </b> or drag it here
</p>
)}
</div>
</div>
);
};
export default Dropzone;
In the app.js
import React, { useCallback,useState } from "react";
import './App.css';
import Form from './components/Form';
import DragDrop from './components/DragDrop';
import ImageList from "./components/ImageList";
import cuid from "cuid";
function App() {
const [images, setImages] = useState([]);
const [errorMessage, setErrorMessage] = useState([]);
const onDrop = useCallback(acceptedFiles => {
// Loop through accepted files
acceptedFiles.map(file => {
// Initialize FileReader browser API
if (!file.name.match(/\.(jpg|jpeg|PNG|gif|JPEG|png|JPG|gif)$/)) {
setErrorMessage('please select valid file image');
//this.setState({ invalidImage: 'Please select valid image.' });
return false;
}
if(file.name.match(/\.(jpg|jpeg|PNG|gif|JPEG|png|JPG|gif)$/)){
const reader = new FileReader();
// onload callback gets called after the reader reads the file data
reader.onload = function(e) {
// add the image into the state. Since FileReader reading process is asynchronous, its better to get the latest snapshot state (i.e., prevState) and update it.
setImages(prevState => [
...prevState,
{ id: cuid(), src: e.target.result }
]);
setErrorMessage();
};
// Read the file as Data URL (since we accept only images)
reader.readAsDataURL(file);
}
return file;
});
}, []);
return (
<main className="App">
<h2 className="App">Drag and Drop Example</h2>
<br />
<div className=".dropzone-div">
<DragDrop onDrop={onDrop} accept={ 'image/*'}/>
</div>
<div className="App">
{errorMessage && <span> {errorMessage} </span>}
<ImageList images={images} />
</div>
</main>
);
}
export default App;
Use an input element with the type as file, like so:
<span>
<label for="upload">Upload</label>
<input id="upload" type="file" accept="image/*" />
</span>
You could of course change the label to your liking, such as an upload icon.
This is a native HTML element that comes with the functionality you want, out of the box. It is tempting to code everything by hand, especially if you're a beginner. Just remember to search for native solutions before you try a new functionality, or even better, familiarize yourself with the docs of the language/framework you're using.
By the way, here's the MDN doc for the file input element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
I am trying to replicate the search and masonry grid from the official documentation using their Codesandbox example.
However, when I am trying to use it, the code is not returning any gifs back.
I have verified that the JS fetch is indeed returning back gifs, it seems that the grid is not calling the fetchGifs function.
I am hitting the same issue with Carousel component as well.
Can anyone help me with this issue?
Codesandbox link for my implementation - https://codesandbox.io/s/cocky-waterfall-ny9rzk
Component i was trying to use - Search and Grid from https://github.com/Giphy/giphy-js/tree/master/packages/react-components
import { GiphyFetch } from "#giphy/js-fetch-api";
import { Grid } from "#giphy/react-components";
import useDebounce from "react-use/lib/useDebounce";
import React, { useState } from "react";
export default function App() {
const giphyFetch = new GiphyFetch("PZpYG85wQpugMlEx02GGqeKfKZ8eMdFZ");
const [debouncedInput, setDebouncedInput] = useState<string>("");
const [term, setTerm] = useState<string>("");
useDebounce(() => setTerm(debouncedInput), 500, [debouncedInput]);
const NoResults = <div className="no-results">No Results for {term}</div>;
const fetchGifs = (offset: number) => {
return giphyFetch.search(term, { offset, limit: 10 });
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<input
placeholder="type to search"
onChange={({ target: { value } }) => setDebouncedInput(value)}
value={debouncedInput}
/>
<Grid
key={term}
columns={3}
gutter={6}
noResultsMessage={NoResults}
width={400}
fetchGifs={fetchGifs}
/>
</div>
);
}
Try removing strict mode here:
https://codesandbox.io/s/cocky-waterfall-ny9rzk?file=/src/index.tsx
I guess the Grid is incompatible with React 18, possibly due to the useEffect change it brings.
Alternatively you could use React 17.x
Updated looks like they've introduced a fix
https://github.com/Giphy/giphy-js/commit/dade2aa10442c9ca8e6741125071dc1053e89181
Hi I have a useEffect question/bug in my code. I would like to have a custom input field to upload an image. So I use useRef and pass it to the ProfileImageOption component. After the upload component the image's get url (avatarUrlPut) is updated and useEffect should call the getPhoto() function and re-render the component. But it is not happenning.
I have found this blogpost related to my issue. But blogpost is not providing a solution idea around the bug. https://coder.earth/post/react-hooks-oops-part-3-an-effect-does-not-run-again-when-its-dependencies-change
I have read from the official documentation that when useRef is used, useEffect will not be able to re-render the component because useRef doesn't notify React when it's current property changes. I suspect a similar issue here but I didn't understand it completely. Would someone help? Thank you.
function EmployeeHeader(props) {
const {avatarUrlPut, avatarUrlPost} = props
const dispatch = useDispatch()
const userID = useSelector((state) => state.auth.fetchUserSuccess.id)
useEffect(() => {
// After uploading the image avatarUrlPut is changed and it is on the dependency array of useEffect
dispatch(getPhoto(avatarUrlPut))
console.log("Am I called after an upload?") // No!
}, [dispatch, avatarUrlPut])
const [uploadedImage, setUploadedImage] = useState({})
const uploadImage = useRef()
const openCameraModal = useRef()
return (
<div>
<ColorizedRect width={'100%'} height={'175px'}>
<Image
source={avatarUrlPut}
className={'profile_image'}
spinnerwidth={'140px'}
spinnerheight={'175px'}
/>
<ProfileImageOption
onClick={() => uploadImage.current.click()}
icon={'upload'}
top={'80px'}
></ProfileImageOption>
<input
id="uploadAvatar"
ref={uploadImage}
type="file"
accept=".jpg,.jpeg,.png,"
style={{display: 'none'}}
onChange={(e) =>
dispatch(uploadPhoto(e.target, avatarUrlPost, setUploadedImage, handleShow))
}
/>
<a href={avatarUrlPut} download="Avatar.jpg">
<ProfileImageOption icon={'download'} top={'125px'}></ProfileImageOption>
</a>
</ColorizedRect>
</div>
)
}
export default EmployeeHeader
This question already has answers here:
How to use comments in React
(15 answers)
Closed 2 years ago.
if I put // to tell the JS compiler that I want to make a comment it renders it however if I place the html syntax it errors and says Parsing
if I used HTML syntax it says Failed to Compile when I use JS it displays text
Here is my Join.js file
import React,{ useState} from 'react';
import {Link} from "react-router-dom";//Link to our /chat path
/*importing my styles*/
import './Join.css';
export default function SignIn() {
//I must always declare hooks within function based
//component and no where else
//first element in index is the nameof the variable and the second is the setter func
//name is a state and setName is a function that is the setter of the state
//I am passing the name Stage an empty string
const [name, setName] = useState('');
//State #2
const [room, setRoom] = useState('');
return (
<div className="joinOuterContainer">
<div className="joinInnerContainer">
<h1 className="heading">Join</h1>
// OnChange Handler: logic of the component happens. When the user types sth in the textbox
//An Event will be raised
return(
<div>
<input placeholder="Name" className="joinInput" type="text" onChange={(event) => setName(event.target.value)}/>
</div>
<div>
<input placeholder="Room" className="joinInput mt-20" type="text" onChange={(event) => setRoom(event.target.value)}/>
</div>
{/*Link will lead us to chat but we have to pass in parameters thanks to the question mark
Prevent the user from logging in if the input validatio usrename and pass are wrong since this will break out app*/}
{/*Raise the event only if the condition is met*/}
<Link onClick={e => (!name || !room) ? e.preventDefault() : null} to={`/chat?name=${name}&room=${room}`}>
<button className="button mt-20" type="submit">Sign In 968 6342 56837</button>
</Link>
</div>
</div>
);
}
You can add comments in jsx using: {}
e.g.
export default function SignIn() {
return <div>
{
// woohoo!
}
{/* oooooh ya */}
</div>
}
I'm trying to focus on the second 'CurrentTextField' after the first 'CurrentTextField' change your value,
but return the error 'inputRef.current is null'
import React, {useRef } from 'react';
import CurrencyTextField from "#unicef/material-ui-currency-textfield";
export default function Clientes() {
let refInput = useRef(null)
return(
<div>
<CurrencyTextField
onChange={(e) => refInput.current.focus()}
/>
<CurrencyTextField
inputRef={refInput}
/>
</div>
)
}
UPDATE 2
I checked again and saw that uses the TextField component from material-ui/core which has a inputProps prop, so this will work
<CurrencyTextField inputProps={{ref:refInput}} />
UPDATE
I just checked the CurrencyTextField source code and it doesn't handle refs
Since you are using the custom component CurrencyTextField you should check if it handles references, when using normal HTML tags you would use the prop ref
export default function Clientes() {
let refInput = useRef(null)
return(
<div>
<CurrencyTextField
onChange={(e) => refInput.current.focus()}
/>
<-- normal input will work -->
<input
ref={refInput}
/>
</div>
)
}
Try to do it like if it were a regular HTML tag to see if it works.
That looks kind of weird. I checked the React documentation and looks good useRef React. Maybe can bring us more details about the library because maybe could be related to your problem