I'm trying to pass 2 sets of state from one component to another so I can have a User's company and name listed in a Header in React. I know I'm getting the right info as I console logged both variables before setting them in my state however, when I try and render them in the Navbar I'm getting undefined.
This is my Header component:
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;
And my Component where I initialise the state:
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;
And my App.js file:
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;
As I said, I'm getting the correct names (company & username) in my console.log but once I've passed them through, nothing is rendering.
I've added my code for the BucketList component and Upload component here too for reference:
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;
Any advice would be greatly appreciated!
question from:
https://stackoverflow.com/questions/65903343/trying-to-pass-state-between-functional-components-but-getting-undefined-error