【发布时间】:2020-01-17 20:45:20
【问题描述】:
我有一个在单个页面上被调用 100 多次的功能组件。在该组件中,我导入 axios 并有一些 axios 调用,这些调用在组件内的各种操作上触发。
由于经验证据,我认为在这个组件中导入 Axios 会显着减慢页面加载速度。假设这是真的,我应该如何提取 axios 的导入以加快速度?
//component.jsx
import React, { useState, useEffect, useMemo } from 'react';
import { useSelector } from 'react-redux'
import { useDropzone } from 'react-dropzone';
import axios from 'axios';
// import fetch from 'isomorphic-fetch';
import { Progress } from 'reactstrap';
import { push } from 'react-router-redux';
import { SERVER_URL } from '../../utils/config';
const baseStyle = {
flex: 1,
display: 'flex',
};
const activeStyle = {
borderColor: '#2196f3'
};
const acceptStyle = {
borderColor: '#00e676'
};
const rejectStyle = {
borderColor: '#ff1744'
};
function StyledDropzone(props) {
const token = useSelector(state => state.auth.token);
const files = props.inputProps.files;
const [myFiles, setFiles] = useState(props.inputProps.files);
const {acceptedFiles, getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject} = useDropzone({
getFilesFromEvent: event => myCustomFileGetter(event, props),
accept: 'image/*,*.doc,*.doc,*.xls*,*.pdf',
onDrop: (acceptedFiles, rejectedFiles) => {
let accepted = acceptedFiles.map(async file => {
setFiles(props.inputProps.files.unshift(file));
let formData = new FormData();
formData.append("file", file);
formData.append("filename", file.name)
formData.append("control", props.inputProps.id);
let item = await axios.post(`${SERVER_URL}/api/v1/requirements/related_files`, formData, {
headers: {
Accept: 'application/json, text/plain, */*',
Authorization: `Token ${token}`,
},
// receive two parameter endpoint url ,form data
})
.then(res => { // then print response status
return Object.assign(file, {
preview: URL.createObjectURL(file),
file_name: response.data.filename
});
res.json()
})
.then((data) => {
console.log('success')
console.log(data);
})
.catch(err => {
if (error && typeof error.response !== 'undefined' && error.response.status === 401) {
// Invalid authentication credentials
return error.response.json().then((data) => {
dispatch(authLoginUserFailure(401, data.non_field_errors[0]));
dispatch(push(loginPath));
});
} else if (error && typeof error.response !== 'undefined' && error.response.status >= 500) {
// Server side error
dispatch(authLoginUserFailure(500, 'A server error occurred while sending your data!'));
} else {
// Most likely connection issues
dispatch(authLoginUserFailure('Connection Error', 'An error occurred while uploading the file'));
}
dispatch(push(loginPath));
return Promise.resolve();
});
return item;
});
}
});
const formattedFileList = files.map(f => (
<li className="fileListItem" key={f.id}>
{f.name ? f.name : f.filename}: <input type="text" placeholder="Add a note..."/> <span className="oi oi-pencil" title="Edit the meta information of this file." aria-hidden="true"></span> <span className="oi oi-data-transfer-download" title="Download this file." aria-hidden="true"></span> <span className="oi oi-x" onClick={() => { deleteFile(f.id) }} title="Delete this file." aria-hidden="true"></span>
</li>
));
const deleteFile = (id) => {
alert(id)
}
// const {
// isDragActive,
// isDragAccept,
// isDragReject
// } = useDropzone({accept: 'image/*,*.doc,*.doc,*.xls*,*.pdf'});
const style = useMemo(() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}), [
isDragActive,
isDragReject
]);
return (
<React.Fragment>
<div {...getRootProps({style})}>
<input {...getInputProps({ id: props.inputProps.id })} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
<label className="control-label">Files</label>
<ul className="fileList">{formattedFileList}</ul>
</React.Fragment>
);
}
async function myCustomFileGetter(event, props) {
const files = [];
const fileList = event.dataTransfer ? event.dataTransfer.files : event.target.files;
for (var i = 0; i < fileList.length; i++) {
const file = fileList.item(i);
Object.defineProperty(file, 'myProp', {
value: true
});
files.push(file);
}
return files;
}
export default StyledDropzone;
【问题讨论】:
-
我认为导入 axios 对性能影响不大。在许多情况下,大量不必要的状态更新(重新渲染)是导致速度变慢的主要原因。你能发布你的组件吗?
-
@YuruiZhang 已更新,谢谢。问题是,在用户请求加载该组件之前,甚至不会渲染每个组件。
-
不确定是什么导致了缓慢。我怀疑
useDropzone的初始化可能很慢——因为每次渲染这个组件时你都给它一个新的对象(带有新的函数)——它可能会重新计算道具并将新的函数返回给你的组件。 -
谢谢@YuruiZhang。这听起来合乎逻辑。我会继续挖掘。
标签: reactjs import axios fetch react-hooks