I am trying to work on a simple image editor using cropperjs and react, I want my project to let the user upload an image crop it and then download it I am using the browser local storage to store the user's image then I am importing the image from local storage to the canvas, if the user does not upload an image I have a default image to let the user play with.
The local storage is storing the user image properly and download is also working for me but my problem is that the local storage image is not coming to canvas and it shows only the default image.
here is my upload form component code
import React from 'react';
const UploadForm = ({uploader}) => {
const handleChange = (e) =>{
uploader(e.target.files[0])
}
return <form>
<input type="file" accept ="image/*" onChange ={handleChange}/>
</form>;
}
export default UploadForm;
and here is my App component code
import React, { useState, useEffect } from 'react';
import Cropper from './comps/cropper.jsx';
import UploadForm from './comps/UploadForm.jsx';
const App = () => {
const [url, setUrl] =useState('');
const uploader = (file) =>{
const reader = new FileReader();
reader.addEventListener('load', ()=>{
localStorage.setItem('recent-image',reader.result)
})
reader.readAsDataURL(file);
}
useEffect(() => {
setUrl(localStorage.getItem('recent-image'));
}, [])
return (
<div>
<UploadForm uploader = {uploader}/>
<Cropper src ={url}/>
</div>
);
}
export default App;
and here is my cropper component code
import React, { Component } from 'react'
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.min.css';
import './cropper.css'
import image from '../image.png';
export class cropper extends Component {
state= {
imageDestination:""
}
imageElement = React.createRef();
componentDidMount(){
const cropper = new Cropper(this.imageElement.current, {
// zoomable:true,
scalable:true,
aspectRatio:1,
crop:()=>{
const canvas = cropper.getCroppedCanvas();
this.setState({
imageDestination:canvas.toDataURL('image/png')
})
}
});
}
render() {
return (
<div>
<div className ="img-container">
<img ref ={this.imageElement} src ={this.props.src||image} alt ="source"/>
</div>
<img src = {this.state.imageDestination} className = "img-preview" alt ="Destination" />
{this.state.imageDestination&&<a href ={this.state.imageDestination}
download>Download</a>
}
</div>
)
}
}
export default cropper
in cropper.jsx, you export the class cropper and also export default cropper in the end of the file too.
export class cropper extends Component
export default cropper
Maybe that's what is causing the issue
Related
Hi this is my first React app im trying to build.
I'm trying to show a random image in React but i can't get
the image to show.
import React from 'react';
function ImageList(props) {
console.log(props);
return (
<div><img src={props} alt="cat"/></div>
);
}
export default ImageList;
the props looks like this:
props: "https://images.unsplash.com/photo-1568152950566-c1bf43f4ab28?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzNTkxNzd8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjE3NTY3NTc&ixlib=rb-1.2.1&q=80&w=400"
When i inspect the img it says object Object.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css'
import ImageList from './ImageList';
const App = () => {
const [cats, setCats] = useState("");
async function onSearchSubmit(term) {
const response = await axios.get('https://api.unsplash.com/photos/random/',{
params: { query: term},
headers:{
Authorization: 'Client-ID //here i just where i put my key in '
}
});
setCats(response.data.urls.small);
}
return(
<div className='App'>
<button onClick={() => {onSearchSubmit("cat")} }>
Show a cat picture
</button>
<ImageList props = {cats}/>
</div>
);}
export default App;
This is the rest of the code.
I am thankful for your help. Cheers!
props it's just the name of your prop.
Look at this row:
<ImageList props = {cats}/>
You shouldn't use the props name for your props. Use some meaningful name instead, like cats
<ImageList cats = {cats}/>
// And in ImageList
const ImageList = ({cats}) => {
// do something with cats. Now it must be a string
}
OR
// props is an object
const ImageList = (props) => {
const cats = props.cats
// do something with cats. Now it must be a string
}
I can't seem to be able to skip to a particular time using ReactPlayer.
Here's my code.
import React, { useRef } from "react";
import ReactPlayer from "react-player";
function VideoPlayer(props) {
const { video, setCurrTime, setAddComment } = props;
const playerRef = useRef();
const writeComments = () => {
if (playerRef.current) {
setCurrTime(playerRef.current.getCurrentTime());
setAddComment(true);
}
};
return (
<div className="player-wrapper">
<ReactPlayer
ref={playerRef}
className="react-player"
width="100%"
height="100%"
url={`http://127.0.0.1:8000${video.video}`}
controls
onPause={writeComments}
/>
</div>
);
}
export default VideoPlayer;
I suspect it might be the file format, MP4.
Unfortunately playerRef doesn't get set to a value you can use.
First caveat: https://github.com/cookpete/react-player/issues/1508
This is an open issue about React's StrictMode often enabled on new projects for React 18. It breaks setting src on the player so it doesn't work. If you upgrade to React 18, the simplest but not ideal solution is to disable React.StrictMode.
If your player is loading, you're on React 17 or you are not using StrictMode.
So if your video is loading, use ReactPlayer's onReady to set your playerRef. player passed into your onReady handler is the actual instance of ReactPlayer which has the methods you are looking for.
import React, { useRef } from "react";
import ReactPlayer from "react-player";
function VideoPlayer(props) {
const { video, setCurrTime, setAddComment } = props;
const playerRef = useRef();
const writeComments = () => {
if (playerRef.current) {
setCurrTime(playerRef.current.getCurrentTime());
setAddComment(true);
}
};
return (
<div className="player-wrapper">
<ReactPlayer
className="react-player"
width="100%"
height="100%"
url={`http://127.0.0.1:8000${video.video}`}
controls
onPause={writeComments}
onReady={(player) => playerRef.current = player}
/>
</div>
);
}
export default VideoPlayer;
I am creating a React component using an npm wysiwyg. When the page loads, I grab some user data from a context I have set up. I grab the user's name and cover letter which is some html code. When the page loads I want to change the wysiwyg's state to contain the cover letter that way it displays it to the user. It works the first time the page loads, however if I hit refresh or try to open the page again, the contents of the wysiwyg disappear. Upon inspection of the console, I am met with a
Warning: Can't call `setState` on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the n component.
I am unsure of what I am doing wrong.
Here is my component:
import React, { useContext, useEffect, useState } from 'react';
import { LoggedInContext } from './contexts/LoggedIn';
import { Editor } from 'react-draft-wysiwyg';
import { EditorState, ContentState } from 'draft-js';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import htmlToDraft from 'html-to-draftjs';
import './Profile.css';
const ProfileSettings = () => {
const { user, coverLetter } = useContext(LoggedInContext);
const blocksFromHtml = htmlToDraft(coverLetter);
const { contentBlocks, entityMap } = blocksFromHtml;
const contentState = ContentState.createFromBlockArray(
contentBlocks,
entityMap
);
const editorState = EditorState.createWithContent(contentState);
const [editorStateReact, setEditorStateReact] = useState(editorState);
const onEditorStateChange = (editorState) => {
setEditorStateReact(editorState);
};
return (
<div className="Profile">
<h2>User: {user}</h2>
<Editor
editorState={editorStateReact}
toolbarClassName="toolbarClassName"
wrapperClassName="wrapperClassName"
editorClassName="editorClassName"
onEditorStateChange={onEditorStateChange}
/>
<button className="btn btn-lg btn-primary my-3">Save Profile</button>
</div>
);
};
export default ProfileSettings;
I am trying to implement draft js as text editor into my next.js project. I have implemented all code based on official guide but the text editor won't show. Here is my code
index.js
import React, { Component } from 'react'
import { useRouter, Router } from 'next/router';
import Layout from '../../components/MyLayout';
import Settings from '../../components/Settings';
import MyEditor from '../../components/TextEditor';
import fetch from 'isomorphic-unfetch';
import {Editor, EditorState} from 'draft-js';
const Post = (props) => {
const router = useRouter();
const object = props.post.data[0];
return (
<Layout>
<h1>{object.title}</h1>
<div className="p-2 border bg-light text-right text-dark">Oleh: {object.username}</div>
<MyEditor/>
</Layout>
);
}
Post.getInitialProps = async function(context) {
const {id} = context.query;
const FormData = new URLSearchParams();
FormData.append('slug',`${id}`);
const res = await fetch(Settings.api+'viewPost',{
'method': 'POST',
'body': FormData
});
const post = await res.json();
console.log('aw');
return {
post
};
};
export default Post;
TextEditor.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Editor, EditorState} from 'draft-js';
export default function MyEditor() {
const [editorState, setEditorState] = React.useState(
EditorState.createEmpty()
);
return (
<Editor
editorState={editorState}
onChange={setEditorState}
/>
);
}
I really appreciate any answer. Thank you
It looks like you're doing the right thing - Draft-js is very much a low-level editing tool that you can build rich text-editing on top of - I'm guessing that the editor is actually rendering on the page, but you haven't added any toolbars or complex initial state so you're just seeing a blank page.
I reproduced a super basic Next JS example here: https://codesandbox.io/s/naughty-swirles-7nmbf?file=/pages/index.js and you'll see that the editor itself is 'invisible' as there is no styling applied and no toolbar. If you look further into the Draft-js docs you'll see you can apply initial config objects that will give it a basic style (which you can further customize as you wish).
I am attempting to create a Web IDE sort of like Eclipse Orion. The code editor that I plan to use is Code Mirror; the only difficulty is that I cannot get the code editor to load. Here is the error that I am encountering.
Here is the code that got me to this issue.
import React, { Component } from 'react';
import codemirror from 'codemirror';
import 'codemirror/mode/markdown/markdown';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/monokai.css';
class Editor extends Component {
componentDidMount = () => {
this.codeMirror = codemirror.fromTextArea(this.codeEditor, {
mode: 'markdown'
});
};
codeEditor = React.createRef();
render = () => (
<div>
<textarea ref={this.codeEditor} />
</div>
);
}
export default Editor;
This issue has been stated many times here, but with no solution that made sense in my situation. Thanks in advance.
This code seemed to do the trick, it was just an issue with the ref.
import React, { Component } from 'react';
import codemirror from 'codemirror';
import 'codemirror/mode/markdown/markdown';
import 'codemirror/lib/codemirror.css';
class Editor extends Component {
componentDidMount = () => {
this.codeMirror = codemirror(this.editor, {
mode: 'markdown'
});
};
ref = React.createRef();
render = () => (
<div>
<div ref={self => this.editor = self} />
</div>
);
}
export default Editor;