javascript - 尝试在功能组件之间传递状态但出现“未定义”错误
问题描述
我正在尝试将 2 组状态从一个组件传递到另一个组件,这样我就可以在 React 的 Header 中列出用户的公司和名称。我知道我得到了正确的信息,因为我在将它们设置为我的状态之前控制台记录了这两个变量但是,当我尝试在导航栏中渲染它们时,我得到了未定义。
这是我的 Header 组件:
import React, { useState } from 'react';
import { Route } from 'react-router-dom';
import { LinkContainer } from 'react-router-bootstrap';
import { Navbar, Nav, Container, NavDropdown } from 'react-bootstrap';
import SearchBox from './SearchBox';
const Header = ({ companyName, userName }) => {
console.log(userName);
return (
<header className='admin-bar'>
<Navbar bg='white' variant='secondary' expand='lg' collapseOnSelect>
<Container>
<LinkContainer to='/'>
<Navbar.Brand>{companyName}</Navbar.Brand>
</LinkContainer>
<NavDropdown title={userName} id='basic-nav-dropdown'>
<NavDropdown.Item href='#action/3.1'>Profile</NavDropdown.Item>
<NavDropdown.Item href='#action/3.2'>Insights</NavDropdown.Item>
<NavDropdown.Item href='#action/3.3'>Settings</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href='#action/3.4'>Sign Out</NavDropdown.Item>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
</header>
);
};
export default Header;
还有我初始化状态的组件:
import Amplify, { Auth } from 'aws-amplify';
import awsconfig from '../aws-exports';
import React, { useState, useEffect } from 'react';
import Upload from '../components/Upload';
import BucketList from '../components/BucketList';
Amplify.configure(awsconfig);
const FileUploadScreen = () => {
const [companyName, setCompanyName] = useState('');
const [userSession, setUserSession] = useState('');
const [userName, setUserName] = useState('');
const onPageRendered = async () => {
let user = await Auth.currentAuthenticatedUser();
let userToken = user.getSignInUserSession().getIdToken().getJwtToken();
setUserSession(user.getSignInUserSession());
let base64Url = userToken.split('.')[1];
let var1 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
let var2 = decodeURIComponent(
atob(var1)
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join('')
);
let company = var2.substring(
var2.indexOf('company') + 10,
var2.indexOf('aud') - 3
);
console.log(company);
setCompanyName(company);
let userAccountName = var2.substring(
var2.indexOf('"name":') + 8,
var2.indexOf('exp') - 3
);
setUserName(userAccountName);
console.log(userAccountName);
};
useEffect(() => {
onPageRendered();
}, []);
return (
<>
<div className='container main p-5'>
<h3 className='text-center pb-1 font-weight-normal bg-white'>
Upload Files
</h3>
<Upload companyName={companyName} />
<BucketList companyName={companyName} />
</div>
</>
);
};
export default FileUploadScreen;
还有我的 App.js 文件:
import { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { Container } from 'react-bootstrap';
import DashboardScreen from './screens/DashboardScreen';
import FileUploadScreen from './screens/FileUploadScreen';
import Sidebar from './components/Sidebar/Sidebar';
import CompanyProfileScreen from './screens/CompanyProfileScreen';
import InsightsScreen from './screens/InsightsScreen';
import WelcomeScreen from './screens/WelcomeScreen';
import Header from './components/Header';
const App = ({ companyName, userName }) => {
const [isLoading, setIsLoading] = useState(true);
return (
<Router>
<Header companyName={companyName} userName={userName} />
<Sidebar />
<main className=''>
<Container>
<Route path='/company' component={CompanyProfileScreen} />
<Route path='/insights' component={InsightsScreen} />
<Route path='/fileupload' component={FileUploadScreen} />
<Route path='/landscape' component={DashboardScreen} />
<Route path='/' component={WelcomeScreen} exact />
</Container>
</main>
</Router>
);
};
export default App;
正如我所说,我在我的 console.log 中获得了正确的名称(公司和用户名),但是一旦我通过了它们,就什么都没有呈现。
我也在这里添加了 BucketList 组件和 Upload 组件的代码以供参考:
import { useState, useEffect } from 'react';
import AWS from 'aws-sdk';
import { ListGroup } from 'react-bootstrap';
AWS.config.update({
accessKeyId: process.env.REACT_APP_ACCESS_ID,
secretAccessKey: process.env.REACT_APP_ACCESS_KEY,
region: process.env.REACT_APP_REGION,
});
const s3 = new AWS.S3();
const BucketList = ({ companyName }) => {
const [listFiles, setListFiles] = useState([]);
const [isVisible, setIsVisible] = useState(false);
const params = {
Bucket: process.env.REACT_APP_BUCKET_NAME,
Delimiter: '',
};
useEffect(() => {
s3.listObjectsV2(params, (err, data) => {
if (err) {
console.log(err, err.stack);
} else {
setListFiles(data.Contents);
}
});
}, []);
// Filtering correct file names
let files = [];
for (let i = 0; i < listFiles.length; i++) {
let str = listFiles[i].Key;
if (
str.includes('OUTPUT') &&
str !== `${companyName}/` &&
str !== 'OUTPUT' &&
str.startsWith(companyName)
) {
files.push(str);
}
for (let i = 0; i < files.length; i++) {
if (
files[i].endsWith(
'vnd.openxmlformats-officedocument.spreadsheetml.sheet'
)
) {
files[i] = files[i].replace(
'.vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'.xlsx'
);
} else if (files[i].endsWith('.vnd.ms-excel')) {
files[i] = files[i].replace('.vnd.ms-excel', '.csv');
}
}
}
// Adding dynamic class to card for scroll
useEffect(() => {
files.length > 3 && setIsVisible(true);
}, [files.length]);
return (
<div className={`card my-4 ${isVisible ? 'test' : ''}`}>
<div className='card-header'>{companyName} Current Files</div>
<ListGroup className='list-group'>
{files &&
files.map((name, index) => (
<ListGroup.Item key={index}>
{name.split('/').slice(2)}
</ListGroup.Item>
))}
</ListGroup>
</div>
);
};
export default BucketList;
import React, { useRef, useState, Fragment, useEffect } from 'react';
import { ListGroup } from 'react-bootstrap';
import Message from './Message';
import ProgressBar from './ProgressBar';
import AWS from 'aws-sdk';
const Upload = ({ companyName }) => {
const bucketName = process.env.REACT_APP_BUCKET_NAME;
const fileInput = useRef();
const [filename, setFilename] = useState('Choose File');
const [message, setMessage] = useState('');
const [fileInfos, setFileInfos] = useState([]);
const [progress, setProgress] = useState(0);
const [showProgressBar, setShowProgressBar] = useState(false);
const [isScroll, setIsScroll] = useState(false);
const selectFile = (e) => {
setFilename(e.target.files[0].name);
};
const handleClick = (event) => {
event.preventDefault();
let newArr = fileInput.current.files;
for (let i = 0; i < newArr.length; i++) {
handleUpload(newArr[i]);
}
};
AWS.config.update({
accessKeyId: process.env.REACT_APP_ACCESS_ID,
secretAccessKey: process.env.REACT_APP_ACCESS_KEY,
});
const myBucket = new AWS.S3({
params: {
Bucket: `${bucketName}/${companyName}`,
},
region: process.env.REACT_APP_REGION,
});
const handleUpload = (file) => {
const params = {
ACL: 'public-read',
Key: file.name,
ContentType: file.type,
Body: file,
};
let newFileName = file.name;
myBucket
.putObject(params)
.on('httpUploadProgress', (evt) => {
setProgress(Math.round((evt.loaded / evt.total) * 100));
setFileInfos([newFileName, ...fileInfos]);
setMessage('File uploaded');
})
.send((err) => {
if (err) {
console.log(err);
setShowProgressBar(false);
setMessage('Could not upload file');
}
});
};
useEffect(() => {
fileInfos.length >= 2 && setIsScroll(true);
}, [fileInfos.length]);
if (progress === 100) {
setTimeout(() => {
setProgress(0);
setShowProgressBar(false);
setMessage('');
}, 3000);
}
return (
<Fragment>
<form className='bg-white my-4' onSubmit={handleClick}>
{message ? <Message msg={message} /> : null}
<div className='custom-file mb-2'>
<input
type='file'
onChange={selectFile}
multiple
ref={fileInput}
id='customFile'
className='custom-file-input'
/>
<label className='custom-file-label' htmlFor='customFile'>
{filename}
</label>
</div>
{showProgressBar ? <ProgressBar percentage={progress} /> : null}
<input
type='submit'
value='Upload'
className='btn btn-primary btn-block mt-3'
disabled={filename === 'Choose File'}
onClick={() => setShowProgressBar(true)}
/>
<br />
<div className={`card ${isScroll ? 'test' : ''}`}>
<div className='card-header'>Recently Added</div>
<ListGroup className='list-group'>
{fileInfos &&
fileInfos.map((file, index) => (
<ListGroup.Item key={index}>{file}</ListGroup.Item>
))}
</ListGroup>
</div>
</form>
</Fragment>
);
};
export default Upload;
任何建议将不胜感激!
解决方案
您必须将以下依赖项添加到您的 useEffect 挂钩中,以便在您获得公司名称和用户名时更新:
useEffect(() => {
onPageRendered();
}, [companyName, userName]);
推荐阅读
- javascript - 如果如何编写一个简单的计数脚本
- javascript - 异步函数不打印除 null 之外的任何输出
- postgresql - 如何通过 cell_id 按日期(时间戳)查找最大值
- validation - 验证错误后如何在primefaces中输入输入
- javascript - Mongodb find方法不返回任何内容
- javascript - 将 Javascript 变量传递给 PHP
- haskell - 是否不可能在 Traversable 中获取元素的深度?
- azure - 如何设置 Azure CDN
- angular - Springboot / login 控制器从角度应用程序失败
- time - 是否有将分钟数的十进制值转换为持续时间格式的值的公式?