Apower96 Apower96 -4 years ago 141
React JSX Question

Rotating image preview with ReactJS

I'm trying to rotate a preview of an image with ReactJS. So I'm first allowing an upload function that renders the preview, and then before the user hits upload I want them to have the option to rotate the image to their liking. This is what I'm using to preview the image:

class ImageUpload extends React.Component {
constructor(props) {
super(props);
this.state = {file: '',imagePreviewUrl: ''};
}

_handleImageChange(e) {
e.preventDefault();

let reader = new FileReader();
let file = e.target.files[0];

reader.onloadend = () => {
this.setState({
file: file,
imagePreviewUrl: reader.result
});
}

reader.readAsDataURL(file)
}

render() {
let {imagePreviewUrl} = this.state;
let $imagePreview = null;
if (imagePreviewUrl) {
$imagePreview = (<img src={imagePreviewUrl} />);
} else {
$imagePreview = (<div className="previewText"></div>);
}

return (
<div className="previewComponent">
<form onSubmit={(e)=>this._handleSubmit(e)}>
<input className="fileInput"
type="file"
onChange={(e)=>this._handleImageChange(e)} />
<button className="submitButton"
type="submit"
onClick={(e)=>this._handleSubmit(e)}>Upload Image</button>
</form>
<input type="button" value="< rotate" onClick="" />
<input type="button" value="rotate >" onClick="" />
<div className="imgPreview">
{$imagePreview}
</div>
</div>
)
}}

ReactDOM.render(<ImageUpload/>, document.getElementById("mainApp"));


And this is what I was trying to use to rotate the image:

class RotateIMG extends React.Component{
constructor(props){
super(props);
this.state = {
rotation: 0
}

this.rotate = this.rotate.bind(this);
this.rotateleft = this.rotateleft.bind(this);
}

rotate(){
let newRotation = this.state.rotation + 90;
if(newRotation >= 360){
newRotation =- 360;
}
this.setState({
rotation: newRotation,
})
}

rotateleft(){
let newRotation = this.state.rotation - 90;
if(newRotation >= 360){
newRotation =- 360;
}
this.setState({
rotation: newRotation,
})
}

render(){
const { rotation } = this.state;
return <div><img style={{transform: `rotate(${rotation}deg)`}} src={"//blog-assets.risingstack.com/2016/Jan/react_best_practices-1453211146748.png"} width="600" />
<input onClick={this.rotateleft} type="button" value="left" />
<input onClick={this.rotate} type="button" value="right" />
</div>
}
}

const element = <RotateIMG />

ReactDOM.render(element, document.getElementById('root'));


As far as I can tell both of these seem to work fine on their own, but I have no idea where to start in terms of making them work together, or if that is even possible. Any help would be greatly appreciated!

Answer Source

Looks like you are really close! You actually have a good structure setup for conditional rendering in your render method, now instead of returning a div, return the RotateIMG component:

import RotateIMG from './rotateIMG.js';
...
render() {
    const { imagePreviewUrl } = this.state;
    let $imagePreview = null;
    if (imagePreviewUrl) {
      $imagePreview = <RotateIMG src={imagePreviewUrl} />;
    } else {
      $imagePreview = <div className="previewText"></div>;
    }
    ...
}

Then you'll need to tweak your RotateIMG component to make sure it's exported and stop rendering it directly to the root.

export default class RotateIMG extends React.Component{
  ...
  render(){
    const { rotation } =  this.state;
    return <div><img style={{transform: `rotate(${rotation}deg)`}} src={this.props.src} width="600" />
      <input onClick={this.rotateleft} type="button" value="left" />
      <input onClick={this.rotate} type="button" value="right" />
    </div>
  }
}

Remove the following from the RotateIMG component

const element = <RotateIMG /> 

ReactDOM.render(element, document.getElementById('root'));
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download