div 클릭 시 열린 파일 브라우저 반응
내 반응 구성요소:
import React, { PropTypes, Component } from 'react'
class Content extends Component {
handleClick(e) {
console.log("Hellooww world")
}
render() {
return (
<div className="body-content">
<div className="add-media" onClick={this.handleClick.bind(this)}>
<i className="plus icon"></i>
<input type="file" id="file" style={{display: "none"}}/>
</div>
</div>
)
}
}
export default Content
여기서 아이콘이 있는 div를 클릭할 때 다음을 엽니다.<input>
사진을 선택할 수 있는 옵션을 보여 주는 파일입니다.사진을 선택한 후 어떤 사진을 선택했는지 값을 받고 싶습니다.어떻게 반응할 수 있을까요?
먼저, 고객용 참조 후크를 만듭니다.input
.
const inputFile = useRef(null)
// or, for TypeScript
// const inputFile = useRef<HTMLInputElement | null>(null);
그리고 나서 그것을 당신의input
스타일을 추가하다display: none
화면을 가리기 위해서요.
<input type='file' id='file' ref={inputFile} style={{display: 'none'}}/>
그런 다음 열린 파일을 처리하는 함수를 만듭니다.이 함수는 현재 사용하고 있는 것과 동일한 기능 내에 있어야 합니다.useRef
갈고리를 채우다
const onButtonClick = () => {
// `current` points to the mounted file input element
inputFile.current.click();
};
그런 다음 함수를button
요소:
<button onClick={onButtonClick}>Open file upload window</button>
단순히 입력 내용을 뷰에 표시하는 것 이외에 입력 내용의 변경에 대처해야 합니다.onChange에서 이 구현을 수행하고 다음과 같이 파일 정보를 열려면 다음과 같이 하십시오.
<input id="myInput"
type="file"
ref={(ref) => this.upload = ref}
style={{display: 'none'}}
onChange={this.onChangeFile.bind(this)}
/>
<RaisedButton
label="Open File"
primary={false}
onClick={()=>{this.upload.click()}}
/>
onChangeFile(event) {
event.stopPropagation();
event.preventDefault();
var file = event.target.files[0];
console.log(file);
this.setState({file}); /// if you want to upload latter
}
콘솔 출력:
File {
name: "my-super-excel-file.vcs",
lastModified: 1503267699000,
lastModifiedDate: Sun Aug 20 2017 19:21:39 GMT-0300 (-03),
webkitRelativePath: "",
size: 54170,
type:"application/vnd.vcs"
}
이제 원하는 대로 작업할 수 있습니다.그러나 업로드하려면 먼저 다음 항목부터 시작해야 합니다.
var form = new FormData();
form.append('file', this.state.file);
YourAjaxLib.doUpload('/yourEndpoint/',form).then(result=> console.log(result));
입력에 ref 속성을 추가합니다.
<input type="file" id="file" ref="fileUploader" style={{display: "none"}}/>
handleClick 함수를 변경합니다.
handleClick(e) {
this.refs.fileUploader.click();
}
ES6를 사용 중이므로 handleClick 함수에 바인드해야 합니다.이 작업은 컨스트럭터에서 수행할 수 있습니다.
constructor (props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
React 16.3은 React.createRef() 메서드를 사용하여 더 나은 접근 방식을 제공합니다.https://reactjs.org/blog/2018/03/29/react-v-16-3.html#createref-api 를 참조해 주세요.
타이프스크립트의 예:
export class MainMenu extends React.Component<MainMenuProps, {}> {
private readonly inputOpenFileRef : RefObject<HTMLInputElement>
constructor() {
super({})
this.inputOpenFileRef = React.createRef()
}
showOpenFileDlg = () => {
this.inputOpenFileRef.current.click()
}
render() {
return (
<div>
<input ref={this.inputOpenFileRef} type="file" style={{ display: "none" }}/>
<button onClick={this.showOpenFileDlg}>Open</Button>
</div>
)
}
}
제시된 답변은 모두 훌륭합니다.이미지를 추가하고 바로 미리 볼 수 있도록 했습니다.리액트 훅을 썼어요
여러분들의 성원에 감사드립니다.
Result should look like the followingimport React, { useEffect, useRef, useState } from 'react';
// Specify camera icon to replace button text
import camera from '../../../assets/images/camera.svg'; // replace it with your path
// Specify your default image
import defaultUser from '../../../assets/images/defaultUser.svg'; // replace it with your path
// Profile upload helper
const HandleImageUpload = () => {
// we are referencing the file input
const imageRef = useRef();
// Specify the default image
const [defaultUserImage, setDefaultUserImage] = useState(defaultUser);
// On each file selection update the default image
const [selectedFile, setSelectedFile] = useState();
// On click on camera icon open the dialog
const showOpenFileDialog = () => {
imageRef.current.click();
};
// On each change let user have access to a selected file
const handleChange = (event) => {
const file = event.target.files[0];
setSelectedFile(file);
};
// Clean up the selection to avoid memory leak
useEffect(() => {
if (selectedFile) {
const objectURL = URL.createObjectURL(selectedFile);
setDefaultUserImage(objectURL);
return () => URL.revokeObjectURL(objectURL);
}
}, [selectedFile]);
return {
imageRef,
defaultUserImage,
showOpenFileDialog,
handleChange,
};
};
// Image component
export const ItemImage = (props) => {
const {itemImage, itemImageAlt} = props;
return (
<>
<img
src={itemImage}
alt={itemImageAlt}
className="item-image"
/>
</>
);
};
// Button with icon component
export const CommonClickButtonIcon = (props) => {
const {
onHandleSubmitForm, iconImageValue, altImg,
} = props;
return (
<div className="common-button">
<button
type="button"
onClick={onHandleSubmitForm}
className="button-image"
>
<img
src={iconImageValue}
alt={altImg}
className="image-button-img"
/>
</button>
</div>
);
};
export const MainProfileForm = () => {
const {
defaultUserImage,
handleChange,
imageRef,
showOpenFileDialog,
} = HandleImageUpload();
return (
<div className="edit-profile-container">
<div className="edit-profile-image">
<ItemImage
itemImage={defaultUserImage}
itemImageAlt="user profile picture"
/>
<CommonClickButtonIcon // Notice I omitted the text instead used icon
onHandleSubmitForm={showOpenFileDialog}
iconImageValue={camera}
altImg="Upload image icon"
/>
<input
ref={imageRef}
type="file"
style={{ display: 'none' }}
accept="image/*"
onChange={handleChange}
/>
</div>
</div>
);
};
나의 CSS
.edit-profile-container {
position: relative;
}
.edit-profile-container .edit-profile-image {
position: relative;
width: 200px;
display: flex;
justify-content: center;
}
.edit-profile-container .edit-profile-image .item-image {
height: 160px;
width: 160px;
border-radius: 360px;
}
.edit-profile-container .edit-profile-image .common-button {
position: absolute;
right: 0;
top: 30px;
}
.edit-profile-container .edit-profile-image .common-button .button-image {
outline: none;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border: none;
background: transparent;
}
.edit-profile-container .edit-profile-image .common-button .image-button-img {
height: 30px;
width: 30px;
box-shadow: 0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
}
레이블로 래핑할 수 있습니다. 레이블을 클릭하면 대화 상자가 클릭됩니다.
<div>
<label htmlFor="fileUpload">
<div>
<h3>Open</h3>
<p>Other stuff in here</p>
</div>
</label>
<input hidden id="fileUpload" type="file" accept="video/*" />
</div>
import React, { useRef, useState } from 'react'
...
const inputRef = useRef()
....
function chooseFile() {
const { current } = inputRef
(current || { click: () => {}}).click()
}
...
<input
onChange={e => {
setFile(e.target.files)
}}
id="select-file"
type="file"
ref={inputRef}
/>
<Button onClick={chooseFile} shadow icon="/upload.svg">
Choose file
</Button>
next.whtml을 사용하여 사용할 수 있는 고유한 코드입니다.
최근에 Material UI에서도 비슷한 기능을 구현하고 싶었지만, 이 접근 방식은 Material UI 프레임워크를 사용하고 Avatar/Badge 컴포넌트를 활용하고 있다는 점을 제외하면 @Niyongabo 구현과 유사합니다.
작업하기 전에 이미지의 크기를 조정합니다.
import React, { useEffect, useRef } from "react";
import List from "@material-ui/core/List";
import t from "prop-types";
import { makeStyles } from "@material-ui/core/styles";
import { Avatar, Badge } from "@material-ui/core";
import withStyles from "@material-ui/core/styles/withStyles";
import IconButton from "@material-ui/core/IconButton";
import EditIcon from "@material-ui/icons/Edit";
import useTheme from "@material-ui/core/styles/useTheme";
import("screw-filereader");
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
"& > *": {
margin: theme.spacing(1)
}
},
form: {
display: "flex",
flexDirection: "column",
margin: "auto",
width: "fit-content"
},
input: {
fontSize: 15
},
large: {
width: theme.spacing(25),
height: theme.spacing(25),
border: `4px solid ${theme.palette.primary.main}`
}
}));
const EditIconButton = withStyles((theme) => ({
root: {
width: 22,
height: 22,
padding: 15,
border: `2px solid ${theme.palette.primary.main}`
}
}))(IconButton);
export const AvatarPicker = (props) => {
const [file, setFile] = React.useState("");
const theme = useTheme();
const classes = useStyles();
const imageRef = useRef();
const { handleChangeImage, avatarImage } = props;
useEffect(() => {
if (!file && avatarImage) {
setFile(URL.createObjectURL(avatarImage));
}
return () => {
if (file) URL.revokeObjectURL(file);
};
}, [file, avatarImage]);
const renderImage = (fileObject) => {
fileObject.image().then((img) => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const maxWidth = 256;
const maxHeight = 256;
const ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
const width = (img.width * ratio + 0.5) | 0;
const height = (img.height * ratio + 0.5) | 0;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob((blob) => {
const resizedFile = new File([blob], file.name, fileObject);
setFile(URL.createObjectURL(resizedFile));
handleChangeImage(resizedFile);
});
});
};
const showOpenFileDialog = () => {
imageRef.current.click();
};
const handleChange = (event) => {
const fileObject = event.target.files[0];
if (!fileObject) return;
renderImage(fileObject);
};
return (
<List data-testid={"image-upload"}>
<div
style={{
display: "flex",
justifyContent: "center",
margin: "20px 10px"
}}
>
<div className={classes.root}>
<Badge
overlap="circle"
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
}}
badgeContent={
<EditIconButton
onClick={showOpenFileDialog}
style={{ background: theme.palette.primary.main }}
>
<EditIcon />
</EditIconButton>
}
>
<Avatar alt={"avatar"} src={file} className={classes.large} />
</Badge>
<input
ref={imageRef}
type="file"
style={{ display: "none" }}
accept="image/*"
onChange={handleChange}
/>
</div>
</div>
</List>
);
};
AvatarPicker.propTypes = {
handleChangeImage: t.func.isRequired,
avatarImage: t.object
};
export default AvatarPicker;
후크를 사용해도 괜찮다면 이 패키지는 입력 요소를 만들지 않고도 문제를 해결할 수 있습니다.이 패키지는 html 입력 요소를 렌더링하지 않습니다.단순히 div 요소에 OnClick을 추가할 수 있습니다.
작업 데모: https://codesandbox.io/s/admiring-hellman-g7p91?file=/src/App.js
import { useFilePicker } from "use-file-picker";
import React from "react";
export default function App() {
const [files, errors, openFileSelector] = useFilePicker({
multiple: true,
accept: ".ics,.pdf"
});
if (errors.length > 0) return <p>Error!</p>;
return (
<div>
<div
style={{ width: 200, height: 200, background: "red" }}
onClick={() => openFileSelector()}
>
Reopen file selector
</div>
<pre>{JSON.stringify(files)}</pre>
</div>
);
}
open File Selector()를 호출하면 브라우저 파일실렉터가 열립니다.
파일 속성:
lastModified: number;
name: string;
content: string;
https://www.npmjs.com/package/use-file-picker
저는 같은 문제를 해결하기 위해 이 패키지를 만들었습니다.
언급URL : https://stackoverflow.com/questions/37457128/react-open-file-browser-on-click-a-div
'programing' 카테고리의 다른 글
Facebook을 WordPress 등록/로그인에 통합하는 방법 (0) | 2023.03.31 |
---|---|
React에 필요한 프로포즈를 1개 이상 포함 (0) | 2023.03.31 |
NextJs CORS 문제 (0) | 2023.03.31 |
기본적으로는 Spring Boot에서는 뷰가 저장되는 장소는 어디입니까? (0) | 2023.03.31 |
Wordpress 사용자 지정 게시 유형 레이블 이름 가져오기 (0) | 2023.03.31 |