So I was working on building functionality for a table on this practice application i'm working on and I started having some weird issues with my buttons not working. In it's current state, the button in the table works, but the button at the top of the page does not work. If I delete the button at the top of the page the button in the table will stop working. The button in the table will also stop working if I remove any of the other 's in the table. I'm pretty stumped as to what could be causing this. If I place any or either of the buttons into the custom Sidebar component they work just fine. I'm new to using hooks so i'm wondering if it's some kind of scope or binding issue but I can't find any results that seem to match this issue using functional components. Apologies for the long file, the top button is at the top near the return statement, the table button is at the bottom of the table towards the bottom of the returned div.
Edit: Here is a link to the project in codesandbox.io I had to rip out the sign in process which hopefully wasn't related In codesandbox.io the top button still doesn't work unless it's in the sidebar but it does not affect the bottom button
https://codesandbox.io/s/inspiring-lichterman-i2688?file=/src/components/Dashboard.js:2867-2924
import {auth} from "../firebase";
import Sidebar from 'react-sidebar'
import menuImage from '../resources/menu.png'
import profileImage from '../resources/profile.png'
import chart from '../resources/piechart.jpeg'
import IncomeModal from './IncomeModal.js';
import './Dashboard.css'
const Dashboard = () => {
const [sidebarOpen, setSidebarOpen] = useState(true)
const [userData, setUserData] = useState(null)
const [isLoading, setIsLoading] = useState(true)
const [isIncomeModal, setIncomeModal] = useState(false)
const [newIncome, setNewIncome] = useState(0)
const [submissionInProgress, setSubmissionInProgress] = useState(false)
const [purchaseArray, setPurchaseArray] = useState([])
function showIncomeModal() {
setSidebarOpen(false)
return setIncomeModal(true)
}
function hideIncomeModal() {
return setIncomeModal(false)
}
const onChangeHandler = (event) => {
const {name, value} = event.currentTarget;
if(!submissionInProgress) {
if(name === 'newIncome') {
setNewIncome(value);
}
}
}
async function postNewIncome(newIncomeVal) {
let url = `placeholder`
let newIncomeNumber = Number(newIncomeVal)
let testBody = {
uid: auth.currentUser.uid,
newIncome: newIncomeNumber
}
console.log(testBody)
const response = await fetch(url, {
method: 'POST',
headers: {
clientSecret: 832195,
'Content-Type': 'application/json'
},
body: JSON.stringify(testBody)
})
return response;
}
function submitNewIncome() {
if(submissionInProgress) {
return
} else {
setSubmissionInProgress(true)
postNewIncome(newIncome).then(()=> {
hideIncomeModal()
refreshUserData()
setSidebarOpen(true)
setSubmissionInProgress(false)
})
}
}
function refreshUserData() {
setIsLoading(true)
getUser().then(data => {
setUserData(data)
}).catch(error => {
console.error('error fetching user data:', error)
}).finally(()=> {
setIsLoading(false)
})
}
function deletePurchase(index) {
console.log(index)
}
useEffect(() => {
refreshUserData()
}, userData)
const navButtonStyle = {
backgroundColor: '#082032',
borderTop: '2px solid #334756',
borderBottom: '2px solid #334756',
borderLeft: 'none',
borderRight: 'none',
color: '#FF4C29',
width: '100%',
padding: '5px'
}
let username = 'loading...'
let income = 'loading'
if(!isLoading) {
username = userData.username
income = `$${userData.income} / month`
}
return (
<div>
<h1 className='title'>Dashboard</h1>
<button onClick={() => console.log('test')}>test</button>
<Sidebar
sidebar={
<div>
<img style={{display: 'block', marginLeft: 'auto', marginRight: 'auto', marginTop:'10px'}} src={profileImage} />
<h2 style={{color: '#FF4C29', textAlign: 'center'}}>{username}</h2>
<div style={{backgroundColor: '#082032', padding:'1px'}}>
<h3 style={{color: '#FF4C29', textAlign: 'center'}}>Income:<br/>{income}</h3>
</div>
<button style={navButtonStyle} onClick = {() => showIncomeModal()}>Set Income</button>
<button style={navButtonStyle} onClick = {() => {auth.signOut()}}>Sign out</button>
</div>
}
open={sidebarOpen}
onSetOpen={setSidebarOpen}
styles={{ sidebar: { background: '#2C394B', width: '15%' } }}>
<button className='menuButton' onClick={() => setSidebarOpen(true)}>
<img style={{margin: '10px', width: '40px'}} src={menuImage} />
</button>
</Sidebar>
<div className='dashboard'>
<div className='display'>
<img style={{display: 'block', marginLeft: 'auto', marginRight: 'auto'}} src={chart} />
</div>
<br/>
<div className='flexbox'>
<div className='flexdisplay'>
<h3>Purchases</h3>
<table>
<tr>
<th>Name</th>
<th>Cost</th>
<th></th>
</tr>
<tr>
<td>ark</td>
<td>$15.00</td>
</tr>
<tr>
<td>ark</td>
<td>$15.00</td>
</tr>
<tr>
<td>last</td>
<td>$16.00</td>
<td><button onClick={() => console.log('value')}>x</button></td>
</tr>
</table>
</div>
<div className='flexdisplay'>
<p>Recurring Expenses</p>
<img style={{display: 'block', marginLeft: 'auto', marginRight: 'auto'}} src={chart} />
</div>
</div>
</div>
<IncomeModal show={isIncomeModal} handleClose={hideIncomeModal}>
<h1>Update Income</h1>
<input
type='number'
name="newIncome"
value = {newIncome}
placeholder=""
id="newIncomeInput"
style={{margin: 10}}
onChange = {(event) => onChangeHandler(event)}
/>
<button onClick={() => submitNewIncome()}>Submit</button>
</IncomeModal>
</div>
)
};
async function getUser() {
let uid = auth.currentUser.uid
let url = `placeholder`
const response = await fetch(url, {
method: 'GET',
headers: {
clientSecret: 832195
}
})
return response.json();
}
// async function setIncome() {
// }
export default Dashboard;```
CodePudding user response:
It isn't an issue with react but your styles. If you try to Inspect(Ctrl shift C on chrome) the button element outside the sidebar, you'll find that it is overlapped, hence no click is passed to it.
In your codesandbox example, following resets the overlapping divs
document.querySelector('div[role=navigation]>div:nth-child(3)').style.inset='unset'
document.querySelector('div[role=navigation]').style.inset='unset'
The combination of position: absolute
and inset: 0px
is making these components span the entire width. As workaround, I removed the inset but you should better redefine the CSS in a better way.