Scroll into a certain div that is hidden in the beggining - javascript

Im building a web chat app in next.js and i have a emoji picker button that when its clicked the menu of emojis appear.The thing is that in order to the user sees the menu of the emojis he has to scroll down.I have tried scrollIntoView() but it doesnt seem to work,possibly im doing something wrong.
<EmoticonContainer >
{showEmojis && (<Picker id="picker" style={{width: '100%'}} onSelect={addEmoji}/>)}
</EmoticonContainer>
<InputContainer id="container" >
<IconButton onClick={() => {setShowEmojis(!showEmojis),()=>document.getElementById('picker').scrollIntoView(true)}}>
<EmojiEmotionsIcon style={{ color: 'purple' }} fontSize='inherit' />
</IconButton>
<Input style={{fontFamily:"Roboto",fontSize:"12px"}} onKeyUp={()=>ChangeSendIcon()} onKeyPress={(e) => { e.key === 'Enter' && e.preventDefault(); }} value={input} onChange={e=> setInput(e.target.value)}/>
<div>
<IconButton id="send" onClick={sendMessage} style={{ color: 'purple',display:'none' }} disabled={!input} type="submit">
<SendIcon></SendIcon>
</IconButton>
<IconButton style={{ color: 'purple'}} id="record" onMouseUp={()=>record()}>
<MicIcon ></MicIcon>
</IconButton>
<IconButton style={{ color: 'purple',display:"none" }} onClick={()=>stop()} id="stop" >
<StopIcon></StopIcon>
</IconButton>
</div>
</InputContainer>
I have tried this but it doesnt seem to work:
useEffect(() => {
if(showEmojis) {
document.getElementById('picker').scrollIntoView(true)
}
} , [showEmojis])

Instead of document.getElementById('picker').scrollIntoView(true) use the React.useRef() hook.
E.g. at the start of your function
const pickerRef = useRef()
then in your useEffect hook
useEffect(() => {
if(showEmojis) {
pickerRef.current.scrollIntoView(true)
}
} , [showEmojis])
then in your return body
<Picker ref={pickerRef} id="picker" style={{width: '100%'}} onSelect={addEmoji}/>
It's not advised to use javascript query in jsx.

Related

Object is possibly "null" in event.target.files in typescript

I want to upload a csv file and later parse it in json format, I have created a state in which i am setting the file using the HTMLEvent Property.I am using typescript I have defined the possible types while defining the state but I am still getting the error.
import {
Box,
Button,
IconButton,
Modal,
Stack,
LinearProgress,
Typography
} from '#mui/material';
import React, { useState } from 'react';
import UploadIcon from '#mui/icons-material/Upload';
import CancelIcon from '#mui/icons-material/Cancel';
import { csvFileParser } from '../../../utils/csvFileParser';
type Props = {};
const BulkServiceUpload = (props: Props) => {
const [openModal, setOpenModal] = useState(false);
const [filename, setFileName] = useState<File | undefined | null>();
console.log(filename);
const style = {
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 600,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
borderRadius: '1rem',
borderWidth: 0,
p: 4
};
const serviceMasterParser = async () => {
if (filename === null) {
alert('Please select a file');
} else {
const parsedCSVData: object[] = csvFileParser(filename);
console.log(parsedCSVData);
}
};
return (
<>
<Box>
<Button
variant="contained"
color="success"
onClick={() => setOpenModal(true)}
>
<UploadIcon />
Add Service
</Button>
</Box>
<Modal open={openModal} onClose={() => setOpenModal(false)}>
<Stack padding={3} sx={style} spacing={3}>
<Typography marginY={3} variant="h5" fontWeight={600}>
Upload Service in Bulk
</Typography>
<Box
sx={{
border: 'dashed 1px black',
borderRadius: '1rem',
position: 'relative',
background: '#f0f0f0',
'&:hover': {
backgroundColor: '#EFFAF5'
}
}}
>
<Box position="absolute" width="100%" height="100%" p={3}>
<Box display="flex" justifyContent="center" alignItems="center">
<UploadIcon />
<Typography>Bulk Upload Service Master</Typography>
</Box>
<Typography fontSize="10px" textAlign="center">
only .csv file is supported
</Typography>
</Box>
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files[0]!)
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>
<Box
p={1}
display={`${filename === null ? 'none' : 'flex'}`}
justifyContent="space-between"
alignItems="center"
sx={{
background: '#f5f5f5',
borderRadius: '15px'
}}
margin={2}
>
<Typography fontSize={14}>{filename?.name!}</Typography>
<IconButton
color="inherit"
aria-label="delete file"
component="label"
onClick={() => {
setFileName(undefined);
}}
>
<CancelIcon fontSize="small" />
</IconButton>
</Box>
{/* <LinearProgress variant="determinate" value={50} /> */}
</Box>
<Button
variant="contained"
color="success"
onClick={() => serviceMasterParser()}
>
<UploadIcon />
Bulk Upload
</Button>
<Button color="success" fullWidth variant="contained">
Add Single Service
</Button>
</Stack>
</Modal>
</>
);
};
export default BulkServiceUpload;
I don't want any initial value for my file.But If i will take useState value empty it will be by default an undefined value. Which is creating this problem. Please let me know how can I solve this .This is my first question so if I have made any mistake my appologies in advance.
Make sure files exists in the target
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement)?.files?.[0])
}
Hi Everyone I think I have made a small typo error while setting the value of a file
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files[0]!)
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>
I should have used the ! after files and it resolved the issue
<input
type="file"
accept=".csv"
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setFileName((e.target as HTMLInputElement).files![0])
}
style={{
width: '100%',
height: '150px',
cursor: 'pointer',
opacity: '0'
}}
/>

Scroll into a certain div

Im building a web chat app in next.js and i have a emoji picker button that when its clicked the menu of emojis appear.The thing is that in order to the user sees the menu of the emojis he has to scroll down.I have tried scrollIntoView() but it doesnt seem to work,possibly im doing something wrong.
<EmoticonContainer >
{showEmojis && (<Picker id="picker" style={{width: '100%'}} onSelect={addEmoji}/>)}
</EmoticonContainer>
<InputContainer id="container" >
<IconButton onClick={() => {setShowEmojis(!showEmojis),()=>document.getElementById('picker').scrollIntoView(true)}}>
<EmojiEmotionsIcon style={{ color: 'purple' }} fontSize='inherit' />
</IconButton>
<Input style={{fontFamily:"Roboto",fontSize:"12px"}} onKeyUp={()=>ChangeSendIcon()} onKeyPress={(e) => { e.key === 'Enter' && e.preventDefault(); }} value={input} onChange={e=> setInput(e.target.value)}/>
<div>
<IconButton id="send" onClick={sendMessage} style={{ color: 'purple',display:'none' }} disabled={!input} type="submit">
<SendIcon></SendIcon>
</IconButton>
<IconButton style={{ color: 'purple'}} id="record" onMouseUp={()=>record()}>
<MicIcon ></MicIcon>
</IconButton>
<IconButton style={{ color: 'purple',display:"none" }} onClick={()=>stop()} id="stop" >
<StopIcon></StopIcon>
</IconButton>
</div>
</InputContainer>
You are conditionally rendering the picker Component and the showEmojis state is also being set in the same click listener. State updates may be async and you are calling scrollIntoView on element which doesn't exist.
In order to scroll into view once the picker is opened, you need to call scrollIntoView from useEffect once it is opened.
useEffect(() => {
if(showEmojis) {
document.getElementById('picker').scrollIntoView(true)
}
} , [showEmojis])

I want to show and hide a form on toggle of a radio button in React js . Im trying how to use react hooks to hide or show a component on onChange even

Now i have used state hook to hide the Form when the page loads. And upon the click or toggle of the radio I'm able to show the Form, But if i toggle the radio again, the form is not hiding.
This is what i have implemented:
const WelcomeTab = () => {
const [toggle, settoggle] = useState(false);
return (
<React.Fragment>
<Tab.Pane
style={{
borderRadius: '7px',
padding: '30px',
}}
attached={false}
>
<Grid>
<Grid.Row>
<Grid.Column floated="left" width={8}>
<Header
style={{
fontSize: '18px',
fontFamily: 'Nunito-Regular',
color: '#4F4F4F',
}}
>
Welcome Screen
</Header>
</Grid.Column>
<Grid.Column floated="right" width={4}>
<Header
as="h4"
style={{
display: 'flex',
justifyContent: 'space-around',
marginLeft: '30px',
}}
>
Customize
<Radio toggle onChange={() => settoggle({ toggle: !toggle })} />
</Header>
</Grid.Column>
</Grid.Row>
</Grid>
{toggle ? (
<Form style={{ paddingTop: '20px' }}>
<Form.Field>
<label style={lableStyle}>Title</label>
<input style={{ marginBottom: '20px' }} />
<label style={lableStyle}>Message</label>
<TextArea />
</Form.Field>
</Form>
) : null}
</Tab.Pane>
</React.Fragment>
);
};
const lableStyle = {
fontFamily: 'Nunito-Regular',
fontWeight: 400,
color: '#4F4F4F',
fontSize: '15px',
display: 'inline-block',
marginBottom: '10px',
};
export default WelcomeTab;
try to add useEffect hook along with change like below,
you no longer need to {} this is old syntax of setState, using hooks we directly make the changes, hope this helps
useEffect(()=>{},[toggle])
replace this wrong syntax code, i can see its not json its boolean value
<Radio toggle onChange={()=>settoggle({toggle: !toggle})}/>
as this is old syntax not work with hooks, try to implment this instead,
<Radio toggle onChange={()=>settoggle(!toggle)}/>

React native invariant violation: text strings must be rendered within a <Text> component in a form (TextField)

This is my code for a form in React Native which is where i seem to be getting the error. I'm confused as this renders perfectly fine in my web simulator (expo):
working form but I get this error when I use ios simulator. I don't have any conditional logic or spaces/semicolons(at least what i can find) so not sure why I'm getting this error, also i'm using material ui core for my text fields in my form (which is where the error is supposedly coming from if you ref the image above). Any help would be appreciated!! pls help
import React, { useRef, useState } from 'react'
import { StyleSheet, View, Text, Modal } from 'react-native';
import { Formik, Form, FieldArray } from 'formik';
import { makeStyles } from '#material-ui/core/styles';
import { Button, TextField } from "#material-ui/core";
import { recipeService } from '../services/RecipeService';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
textField: {
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
marginTop: theme.spacing(1),
},
}));
export default function NewRecipe({ route }) {
const [showAlert, setShowAlert] = useState(false);
const { userId } = route.params;
const instructions = [''];
const ingredients = [{ name: '', amount: '', optional: false }];
const classes = useStyles();
const input = useRef();
return (
<View style={styles.container}>
<Formik
initialValues={{ userId: userId, name: "", summary: "", instructions: instructions, ingredients: ingredients }}
onSubmit={(values, actions) => {
recipeService.createRecipe(values).then(
(response) => {
console.log(response);
setShowAlert(true);
console.log("alert = " + showAlert);
actions.resetForm({});
return (
<Modal
animationType="slide"
transparent={false}
visible={true}
onRequestClose={
() => { setShowAlert(false); }
}>
<View style={styles.modalView}>
<Text>Recipe saved!</Text>
<Button
margin="normal"
type="button"
variant="contained"
color="default"
className={classes.textField}
onClick={() => actions.resetForm({})}
>
New Recipe
</Button>
</View>
</Modal>
)
}
)
.catch((error) => {
console.log(error);
});
}
}
>{({ values, handleChange, handleBlur }) => (
<Form>
<TextField
fullWidth
variant="outlined"
id="name"
name="name"
label="Name"
value={values.name}
onChange={handleChange}
/>
<TextField
fullWidth
multiline
variant="outlined"
id="summary"
name="summary"
label="Summary"
className={classes.textField}
value={values.summary}
onChange={handleChange}
/>
<View style={styles.row}>
<FieldArray
name="ingredients"
render={arrayHelpers => (
<div>
{values.ingredients.map((item, index) => (
<div key={index}>
<TextField
variant="outlined"
label="Ingredient Name"
name={`ingredients.${index}.name`}
value={item.name}
margin="normal"
className={classes.textField}
onChange={handleChange}
style={{ margin: 8, width: 233 }}
onBlur={handleBlur}
/>
<TextField
variant="outlined"
label="Amount"
name={`ingredients.${index}.amount`}
value={item.amount}
margin="normal"
className={classes.textField}
onChange={handleChange}
style={{ margin: 8, width: 100 }}
onBlur={handleBlur}
/>
<Button
margin="normal"
type="button"
color="secondary"
variant="outlined"
margin="dense"
style={{ margin: 8, width: 30 }}
className={classes.textField}
onClick={() => arrayHelpers.remove(index)}
> x
</Button>
<Button
margin="normal"
type="button"
variant="contained"
color="default"
className={classes.textField}
onClick={() => arrayHelpers.push({ name: '', amount: '', optional: false })}
>Add
</Button>
</div>
))}
</div>
)}
/>
</View>
<FieldArray
name="instructions"
render={arrayHelpers => (
<div>
{values.instructions.map((item, index) => (
<div key={index}>
<TextField
variant="outlined"
label="Instruction"
name={`instructions.${index}`}
value={item}
margin="normal"
className={classes.textField}
onChange={handleChange}
style={{ margin: 8, width: 350 }}
onBlur={handleBlur}
/>
<Button
margin="normal"
type="button"
color="secondary"
variant="outlined"
margin="dense"
style={{ margin: 8, width: 30 }}
className={classes.textField}
onClick={() => arrayHelpers.remove(index)}
> x
</Button>
</div>
))}
<Button
margin="normal"
type="button"
variant="contained"
color="default"
className={classes.textField}
onClick={() => arrayHelpers.push('')}
>Add
</Button>
</div>
)}
/>
<div>
<Button color="primary" variant="contained" className={classes.textField} fullWidth type="submit">
Submit
</Button>
</div>
</Form>
)}
</Formik>
You cannot use #material-ui/core for React Native projects.
#material-ui/core can work for expo because it's web based. But I'm pretty sure that it won't work for native environments.
I'd like to recommend alternatives, but I don't use material design for React Native because it simply doesn't fit to iOS.

Copied code for dialog in material-ui from docs, but isn't working, what am I doing wrong?

I copied code for material-ui dialog feature for react, but couldn't figure out why this isn't working at all. Clicking the contact button doesn't even cause it to call the handleClickOpen method.
The contact button is the one that's supposed to open the dialog box, all the dialog code is copied from the docs of material-ui so I'm not sure how this couldn't be working.
export default function Banner() {
const [open, setOpen] = React.useState(false);
function handleClickOpen() {
setOpen(true);
}
function handleClose() {
setOpen(false);
}
const classes = useStyles();
return (
<Container maxWidth="lg">
<div className={classes.root}>
<Grid container spacing={7}>
<Grid item lg={6} xs={12}>
<div className={classes.title}>
<Title content="Freightage Solutions" />
<br />
<SubTitle content="A lean, modern, and efficient shipping brokerage." />
<div className={classes.buttons}>
<Button ClassName={classes.button} content="Get Started" color='white' />
<Button ClassName={classes.button} content="Contact Us" color='blue' onClick = {handleClickOpen} />
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Use Google's location service?"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Let Google help apps determine location. This means sending anonymous location data to
Google, even when no apps are running.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Disagree
</Button>
<Button onClick={handleClose} color="primary" autoFocus>
Agree
</Button>
</DialogActions>
</Dialog>
</div>
</div>
</Grid>
<Grid item lg={6} xs={12}>
<img src={Image} className={classes.image} />
</Grid>
</Grid>
</div>
</Container>
);
}
EDIT: Here is the custom button component I'm using
import React from 'react';
import Typography from '#material-ui/core/Typography';
import { styled } from '#material-ui/styles';
import createBreakpoints from "#material-ui/core/styles/createBreakpoints";
import Button from "#material-ui/core/Button"
const breakpoints = createBreakpoints({});
const CustomButton = styled(Button)({
border: '2px solid #FFFFFF',
borderRadius: 80,
height: 48,
padding: '0 20px',
textTransform: 'none',
marginBottom: '20px',
marginRight: '30px',
marginLeft: '30px',
[breakpoints.up("lg")]: {
marginLeft: '0px',
},
});
const BlueButton = styled(CustomButton)({
background: '#0071F7',
color: 'white',
'&:hover': {
background: 'white',
color: '#0071F7',
},
});
const WhiteButton = styled(CustomButton)({
background: 'white',
color: '#0071F7',
'&:hover': {
background: '#0071F7',
color: 'white',
}
});
const ButtonType = styled(Typography)({
fontFamily: 'Ubuntu',
fontWeight: 450,
});
export default class Title extends React.Component {
render (){
if(this.props.color == 'white'){
return (
<WhiteButton gutterBottom>
<ButtonType>
{this.props.content}
</ButtonType>
</WhiteButton>
)
} else{
return(
<BlueButton gutterBottom>
<ButtonType>
{this.props.content}
</ButtonType>
</BlueButton>
)
}
}
}
It would be a good idea to use the onClick-prop you provided with to your CustomButton and set it on your button.
export default class Title extends React.Component {
render () {
if(this.props.color == 'white'){
return (
<WhiteButton onClick={this.props.onClick} gutterBottom>
<ButtonType>
{this.props.content}
</ButtonType>
</WhiteButton>
)
} else{
return(
<BlueButton onClick={this.props.onClick} gutterBottom>
<ButtonType>
{this.props.content}
</ButtonType>
</BlueButton>
)
}
}
}
As per the API Doc, there is no props called content for Button instead use children like,
<Button className={classes.button} children="Get Started" style={{color:'white'}} />
<Button className={classes.button} children="Contact Us" style={{color:'blue'}} onClick = {handleClickOpen} />
Update
You are using Button name to your custom component and material-ui also have the component with same name. As you are using both in same place there is a conflict and not a error from material-ui which one to use and your functionality is not working. This is probably the problem.
Try to change your custom button component name and check if it works.
Update 2
if(this.props.color == 'white'){
return (
<WhiteButton gutterBottom>
<ButtonType>
<Button onClick={this.props.onClick}>{this.props.content}</Button> //You forgot to use Button here
</ButtonType>
</WhiteButton>
)
} else{
return(
<BlueButton gutterBottom>
<ButtonType>
<Button onClick={this.props.onClick}>{this.props.content}</Button>
</ButtonType>
</BlueButton>
)
}
you should use proper material-ui Button API(https://material-ui.com/api/button/)
<Button children="Get Started" style={{color:'white'}} />
<Button children="Contact Us" style={{color:'blue'}} onClick = {handleClickOpen} />
check this: https://codesandbox.io/s/3fl8r

Categories