so i'm trying to make my Navbar fixed to the top of the screen when i have scrolled below the actual Navbar. I am using WayPoints onEnter and onLeave to trigger when i have scrolled past. The issue i'm having is, that when styled is equal to false, the {position:'relative'} i believe makes the site crash and i'm not sure why, or what solution is.
import React, { useEffect, useState } from 'react'
import Navbar from './Navbar'
import { Box, Grid, Card, CardMedia, CardActionArea, Typography, CardContent, CardActions, Button }
from '#material-ui/core'
import Styles from './Styles'
import { Random } from 'react-animated-text'
import { projectSections } from './ListItems'
import { Waypoint } from 'react-waypoint';
const Portfolio = () => {
const [styled, setStyled] = useState(false)
const style = () => (
styled==false
? {
position:'fixed',
width:'100%',
zIndex:99
}
: {position:'relative'}
)
const handleWaypointEnter = () => (
setStyled(!styled) )
const handleWaypointLeave = () => (
setStyled(!styled)
)
return (
<>
<Waypoint
onEnter={handleWaypointEnter}
onLeave={handleWaypointLeave}
>
<div style={style()}>
<Navbar/>
</div>
</Waypoint>
{/* Ignore this for now
<Box style={{position:'relative'}}>
<Box component='div'>
<Typography align='center' className={classes.portTitle}>
<Random
className={classes.portTitle}
text="PORTFOLIO"
effect='pop'
effectChange={.8}
effectDuration={1.3}
/>
</Typography>
<Grid container justify='center' alignItems='center' style={{padding:20}}>
{project()}
</Grid>
</Box>
</Box>
*/}
</>
)
}
Have you tried with return statement in style function.
Related
I'm using Material UI 5.10.11 and the MuiAlert component sometimes goes wrong.
This is what it should looks like when severity='error'
However in some pages, it looks like this
Below are my codes. Can anyone have a look at it and try to figure out what's wrong with my work?
import React, { useState, useEffect } from 'react';
import { Snackbar } from '#mui/material';
import MuiAlert from '#mui/material/Alert';
const Alert = React.forwardRef(function Alert(props, ref) {
return <MuiAlert elevation={24} ref={ref} variant="filled" {...props} />;
});
export default function MessageDialog(props) {
const defaultPosition = {
vertical: 'top',
horizontal: 'center'
};
const autoHideDuration = 5000;
const [open, setOpen] = useState(false);
useEffect(() => {
let timeoutId;
if (props.open) {
setOpen(true);
timeoutId = setTimeout(() => {
setOpen(false);
}, autoHideDuration);
}
return () => {
clearTimeout(timeoutId);
};
}, [props.open]);
return (
<>
<Snackbar
anchorOrigin={{
vertical: defaultPosition.vertical,
horizontal: defaultPosition.horizontal
}}
open={open}
>
<Alert severity={props.type} sx={{ width: '100%' }}>
{props.children}
</Alert>
</Snackbar>
</>
);
}
Many thanks in advance!
The fault is due to the css that I spotted out in the screenshots.
It looks like problem comes from Mui component class name which is MuiPaper-root. In page with white background it overrites because probably some other Mui components have same class name and you are using white background with this component or you have a css file with white background assigned to MuiPaper-root class in that page
I wanted to change the style of an item with one click in a list and remove it if I click another item
I did like this but when I click on the second it doesn’t change to the first
const ref = useRef();
const handleClick = () => {
if (ref.current.style.backgroundColor) {
ref.current.style.backgroundColor = '';
ref.current.style.color = '';
} else {
ref.current.style.backgroundColor = 'green';
ref.current.style.color = 'white';
}
};
<Card ref={ref} elevation={6} style={{ marginBottom: "5px"}} onClick={()=>{ handleClick()}} >
<CardContent style={{ height: "10px" }}>
<Typography >
{user}
</Typography>
</CardContent>
</Card>
);
};
any help please!
I like using a package like classnames ( yarn add classnames or npm i classnames) to apply conditional styling through classes rather than having to inline the element's styling directly.
You could pass the selected attribute to your Card component using React's useState (or Redux) and then apply conditional styling to selected cards (i.e. <Card selected />).
Component.js
import { useState } from 'react';
import { useSelector } from 'react-redux';
import Card from './Card';
const Component = () => {
const [selectedId, setSelectedId] = useState(null);
const items = useSelector(state => state.items);
const handleClick = (id) => {
setSelectedId(id);
};
return items.map(({id}) =>
<Card
key={id}
onClick={() => handleClick(id)}
selected={id === selectedId}
>
...
</Card>
);
};
export default Component;
Card.js
import { classNames } from 'classnames';
const Card = ({ children, onClick, selected = false }) => (
<div
className={
classNames('Card', {
'Card--Selected': selected
})
}
onClick={onClick}
>
{ children }
</div>
);
export default Card;
Card.scss
.Card {
// Card styling...
&--Selected {
// Selected card styling...
}
}
I am working with custom Transition component and my inline styling just wont apply. I tried everything what is in my power and just got myself angry. Can somebody explain why this doesn't work.
Modal show itself on initial load and by clicking on button for show or not show this doesn't react. I mean state updates correctly (this console.log shows 0 and 1 when it should) but styling just wont apply.
import classes from "./App.module.css";
import ReactDOM from "react-dom";
import React from "react";
import Modal from "./components/Modal/Modal";
import List from "./components/List/List";
import Backdrop from "./components/Backdrop/Backdrop";
import { useState } from "react";
import Transition from "react-transition-group/cjs/Transition";
function App() {
const [modalOpen, setModalOpen] = useState(false);
const onOpenModalHandler = () => {
setModalOpen(true);
};
const onCloseModalHandler = () => {
setModalOpen(false);
};
return (
<div className={classes["App"]}>
<h1>React Animations</h1>
<Transition in={modalOpen} timeout={1000} onMountEnter onMountExit>
{(state) => {
console.log(state);
console.log(state === "exiting" || state === "exited" ? 0 : 1);
return ReactDOM.createPortal(
<Modal
closeModal={onCloseModalHandler}
modalState={modalOpen}
style={{
transition: `opacity 300ms ease-out`,
opacity: state === "exiting" || state === "exited" ? 0 : 1,
}}
/>,
document.getElementById("modal")
);
}}
</Transition>
{modalOpen &&
ReactDOM.createPortal(
<Backdrop />,
document.getElementById("backdrop")
)}
<button className={"Button"} onClick={onOpenModalHandler}>
Open Modal
</button>
<h3>Animating Lists</h3>
<List />
</div>
);
}
export default App;
Modal
import classes from "./Modal.module.css";
const Modal = (props) => {
const classNames = props.modalState
? `${classes["modal-open"]} ${classes["Modal"]}`
: `${classes["modal-close"]} ${classes["Modal"]}`;
const onCloseModalHandler = () => {
props.closeModal();
};
return (
<div className={classNames}>
<h1>A Modal</h1>
<button className="Button" onClick={onCloseModalHandler}>
Dismiss
</button>
</div>
);
};
export default Modal;
In my React Native (Expo) application, I wanted to upgrade React Navigation from V5 to V6. However, I could not make TextInput in stack navigator header full-width. I tried 'auto' and '100%' for the width value in styling, however neither helped with a real wide textbox.
Here is the link for Expo snack for reproduction: https://snack.expo.io/#vahdet/reactnavigation6-headerbar and the App.js content from it is below. I guess I am short of some flexbox knowledge in headerSearchBarStyle:
import React, { useLayoutEffect, useState } from 'react';
import { Text, TextInput, View, StyleSheet } from 'react-native';
import { NavigationContainer, useNavigation } from '#react-navigation/native';
import { enableScreens } from 'react-native-screens';
import { AppearanceProvider } from 'react-native-appearance';
import { StatusBar } from 'expo-status-bar';
import { createStackNavigator } from '#react-navigation/stack';
enableScreens();
const HomeStack = createStackNavigator();
const Search = () => {
const navigation = useNavigation();
const [searchText, setSearchText] = useState('');
// Customize header
useLayoutEffect(() => {
navigation.setOptions({
headerTitle: () => (
<TextInput
style={styles.headerSearchBarStyle}
value={searchText}
onChangeText={(val) => setSearchText(val)}
containerStyle={styles.searchBarContainerStyle}
placeholder="Search..."
returnKeyType="search"
textContentType="none"
cancelButtonTitle="Cancel"
/>
)
})
}, [navigation, searchText]);
return (
<View style={styles.view}>
{!searchText ? (
<Text>Search results go here</Text>
) : (
<Text>Initial (no search) content goes here</Text>
)}
</View>
)
}
const App = () => {
return (
<AppearanceProvider>
<StatusBar style="auto" />
<NavigationContainer>
<HomeStack.Navigator initialRouteName="Search">
<HomeStack.Screen name="Search" component={Search} />
</HomeStack.Navigator>
</NavigationContainer>
</AppearanceProvider>
);
}
const styles = StyleSheet.create({
headerSearchBarStyle: {
width: 'auto', // also tried '100%'
borderColor: 'black',
borderWidth: 1,
backgroundColor: 'transparent'
},
});
export default App;
EDIT: After Kartikey's approach I want to elaborate that by full-width, I do not necessarily mean the full screen width: There may be scenarios with headerLeft (e.g. back button) or headerRight components at the same time.
Use Device Width
import { Dimensions } from "react-native";
const ScreenWidth = Dimensions.get('window').width;
and
headerSearchBarStyle: {
width: ScreenWidth,
borderColor: 'black',
borderWidth: 1,
backgroundColor: 'transparent',
margin: 10,
},
You can also set it to width: ScreenWidth - 30, just to give some margin
Working Example
I am using Next.js with Material-UI as the framework.
I have Layout component that wraps the contents with Material-UI <Container>.
I would like to override the style of Layout that limits the width of background, so that the background would extend to the full screen.
components/Layout.js
import { Container } from '#material-ui/core';
export default function Layout({ children }) {
return <Container>{children}</Container>;
}
pages/_app.js
import Layout from '../components/Layout';
...
<Layout>
<Component {...pageProps} />
</Layout>
...
pages/index.js
export default function App() {
return (
<div style={{ backgroundColor: "yellow" }}>
Home Page
</div>
)
}
Using Layout component comes in handy in most cases but sometimes I do want to override the certain styles of Layout from the child component.
In this case, how do I override the style of Layout component that puts the limit on maxWidth?
I tried to add {width: '100vw'} inside the style of pages/index.js, but did not work.
Any help would be appreciated.
Link to the SandBox
Using React Context is how I've solved this issue.
context/ContainerContext.js
import React from 'react';
const ContainerContext = React.createContext();
export default ContainerContext;
components/Layout.js
import React, { useState } from 'react';
import { Container } from '#material-ui/core';
import ContainerContext from '../context/ContainerContext';
export default function Layout({ children }) {
const [hasContainer, setHasContainer] = useState(true);
const Wrapper = hasContainer ? Container : React.Fragment;
return (
<ContainerContext.Provider value={{ hasContainer, setHasContainer }}>
<Wrapper>{children}</Wrapper>
</ContainerContext.Provider>
);
}
pages/index.js
import { useContext, useLayoutEffect } from 'react';
import ContainerContext from '../context/ContainerContext';
export default function App() {
const { setHasContainer } = useContext(ContainerContext);
// Where the magic happens!
useLayoutEffect(() => {
setHasContainer(false);
}, []);
return (
<div style={{ backgroundColor: "yellow" }}>
Home Page
</div>
);
}