Reputation: 565
ReactJS newbie question. I'm trying to wrap my EmergencyService.js functional component with forwardRef so that I can reference the ref in SearchBar.js by following this tutorial https://codezup.com/forwardref-in-functional-components-react-hooks/ but when I try doing so I receive an Unexpected Token error. The only edit I made to EmergencyService.js is replace "export default function EmergencyService() {" with "const EmergencyService = (props, ref) => (" on line 158 and added "export default React.forwardRef(EmergencyService);" to the bottom. I'm not sure why this error is occurring. I also tried just wrapping only the return but received the same error. Any help would be greatly appreciated. Please feel free to view my code at https://codesandbox.io/s/twilight-waterfall-3okx4?file=/src/EmergencyService.js
Upvotes: 1
Views: 1868
Reputation: 646
I have gone through your codesandbox. Updated a little bit code, let me know if it helps.
import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import styled from "styled-components";
import { makeStyles } from "@material-ui/core/styles";
import IconButton from "@material-ui/core/IconButton";
import ClearIcon from "@material-ui/icons/Clear";
import clsx from "clsx";
const autocompleteDefaultWidth = 180;
const useStyles = makeStyles((theme) => ({
icon: {
color: theme.palette.text.secondary,
marginRight: theme.spacing(2)
},
searchField: {
marginTop: "-12px",
"& .MuiFilledInput-root": {
background: "none"
},
width: "100%",
transition: "width 0.5s"
},
inputLabel: {
color: "#3c3b37",
backgroundColor: "none",
padding: "0 5px 0 5px",
"&.focused": {
color: "black",
backgroundColor: "#fbfbf8"
}
},
autocompleteBase: {
display: "inline-block",
height: "42px",
transition: "width 0.5s",
paddingLeft: "30px",
//paddingRight: "30px",
borderRadius: "9999px",
minWidth: "210px",
float: "left"
},
autocompleteOnFocus: {
backgroundColor: "#ffffff",
borderBottom: "1px solid #989586",
webkitBoxShadow: "0 2px 4px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.08)",
boxShadow: "0 2px 4px rgba(0,0,0,.08),0 4px 12px rgba(0,0,0,.08)",
transition: "width 0.5s, min-width 0.5s",
minWidth: "285px",
"&:hover $clearIndicatorDirty, & .Mui-focused $clearIndicatorDirty": {
visibility: "visible !important",
right: "8px",
position: "absolute",
top: "4px"
},
"& .MuiInputBase-input": {
width: "100%"
}
},
autocompleteCustom: {
position: "relative",
"&:hover": {
backgroundColor: "#f0f0eb",
cursor: "pointer",
"&::after": {
display: "none"
}
},
"&::after": {
content: '""',
borderRight: "1px solid #ccc9b3",
position: "absolute",
top: "10px",
width: "1px",
right: "0",
height: "20px",
bottom: "0"
},
"& .MuiInputBase-input": {
cursor: "pointer",
width: "calc(100%-20px)"
}
},
autocompleteCustomWithValue: {
minWidth: "180px",
position: "relative",
backgroundColor: "#f0f0eb",
cursor: "pointer",
"&::after": {
display: "none"
},
"& .MuiInputBase-input": {
cursor: "pointer",
width: "calc(100%-20px)"
}
},
clearIndicatorDirty: {
backgroundColor: "rgba(0, 0, 0, 0.04)",
right: "0px"
},
clearIndicator: {
visibility: "hidden"
},
searchFieldWidth: {
whiteSpace: "pre",
fontSize: "16px",
visibility: "hidden"
},
currentLocationLink: {
padding: "12px 0 12px 16px",
borderBottom: "1px solid #0072ff",
fontSize: "16px",
fontWeight: "bold",
color: "#0072ff",
"&:hover": {
backgroundColor: "#f0f0eb",
cursor: "pointer"
}
},
currentLocationLinkMarker: {
color: "#0072ff"
},
autocompleteOption: {
"& ul li": {
"&:hover": {
backgroundColor: "#f0f0eb"
}
}
},
"@global": {
'.MuiAutocomplete-option[data-focus="true"]': {
background: "#f0f0eb"
}
},
listbox: {
padding: 0
}
}));
const EmergencyServiceTextField = styled(TextField)`
.MuiInputLabel-shrink {
background-color: #ffffff;
}
.MuiAutocomplete-endAdornment {
//right: -20px;
//right: 10px;
//top: calc(50%-5px);
}
.MuiAutocomplete-inputRoot[class*="MuiInput-root"]
.MuiAutocomplete-input:first-child {
padding: 8px 0;
}
`;
const EmergencyService = React.forwardRef(({ ...props }, ref) => {
console.log(props, ref);
const classes = useStyles();
const [focused, setFocused] = React.useState(classes.autocompleteCustom);
const [value, setValue] = React.useState(null);
const [inputValue, setInputValue] = React.useState("");
const [inputWidth, setInputWidth] = React.useState(autocompleteDefaultWidth);
const emergencyServiceField = React.useRef();
const handleChange = (v) => {
if (v) {
if ((v !== null) & (v.length > 0)) {
const thisValue = v.toString().toLowerCase();
if (thisValue === "yes") {
setValue("Yes");
setInputValue("Yes");
} else if (thisValue === "no") {
setValue("No");
setInputValue("No");
} else {
setValue(null);
setInputValue(null);
}
}
}
};
React.useEffect(() => {
if (inputValue !== null && inputValue.length > 0) {
setFocused(classes.autocompleteCustomWithValue);
setInputWidth(110);
}
/* if (inputValue === 'yes' || inputValue === 'no') {
setValue(inputValue);
setInputValue(inputValue);
}else{
setValue('test');
setInputValue('test');
}
if (value === 'yes' || value === 'no') {
setValue(value);
setInputValue(value);
}else{
setValue('test');
setInputValue('test');
} */
}, [value, inputValue, inputWidth]);
return (
<div
className={`${focused} ${classes.autocompleteBase}`}
style={{ width: `${inputWidth}px` }}
onMouseDown={(event) => {
event.preventDefault();
emergencyServiceField.current.focus();
}}
>
<Autocomplete
disablePortal
getOptionLabel={(option) =>
typeof option === "string" ? option : option.label
}
options={top100Films}
autoComplete
includeInputInList
filterSelectedOptions
freeSolo
openOnFocus
clearOnBlur
blurOnSelect
handleHomeEndKeys
value={value}
onChange={(event, newValue) => {
handleChange(newValue);
}}
onInputChange={(event, newInputValue) => {
handleChange(newInputValue);
}}
onFocus={() => {
setFocused(classes.autocompleteOnFocus);
}}
onBlur={() => {
if (inputValue !== null && inputValue.length > 0) {
const thisValue = inputValue.toString().toLowerCase();
if (thisValue === "yes" || thisValue === "no") {
setFocused(classes.autocompleteCustomWithValue);
}
} else {
setFocused(classes.autocompleteCustom);
}
}}
onKeyDown={(event) => {
if (event.key !== undefined) {
if (event.key == "Backspace") {
if (emergencyServiceField.current.value.length < 2) {
setValue(null);
setInputValue(null);
}
//console.log('New V = '+emergencyServiceField.current.value);
}
// console.log('key' + event.key);
} else if (event.keyIdentifier !== undefined) {
console.log("keyId" + event.keyIdentifier);
} else if (event.keyCode !== undefined) {
console.log("key Code" + event.keyCode);
}
}}
classes={{
clearIndicatorDirty: classes.clearIndicator,
listbox: classes.listbox
}}
renderInput={(params) => (
<EmergencyServiceTextField
{...params}
inputRef={emergencyServiceField}
className={classes.searchField}
label="Emergency Service"
fullWidth
placeholder="Is emergency service required?"
InputProps={{
...params.InputProps,
disableUnderline: true,
endAdornment: (
<IconButton
className={clsx(classes.clearIndicator, {
[classes.clearIndicatorDirty]:
inputValue !== null && inputValue.length > 0
})}
size="small"
onClick={() => {
setValue("");
setInputValue("");
}}
>
<ClearIcon fontSize="small" />
</IconButton>
)
}}
InputLabelProps={{
classes: {
root: classes.inputLabel,
focused: "focused"
}
}}
/>
)}
/>
</div>
);
})
export default EmergencyService;
// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
{ label: "Yes", value: "Yes" },
{ label: "No", value: "No" }
];
Upvotes: 1
Reputation: 2373
I took a look at your code and I found this error:
SyntaxError
/src/EmergencyService.js: Unexpected token (160:2)
158 | const EmergencyService = (props, ref) => (
159 |
> 160 | const classes = useStyles();
| ^
To fix this, you just need to substitute the (
in line 158 and the closing one )
in line 309. This way, you'll get rid of the auto return
and you can add javascript code to your functional component.
PS: in your current state, the interpreter is expecting JSX code and not JavaScript code since you are in the return statement.
Upvotes: 0