I have tried to display a search icon inside my search bar, but it isn't working. my code is
import React, { useEffect } from "react";
//31915c5e
const API_URL = 'http://www.omdbapi.com?apikey = 31915c5e'
const App = () => {
const searchMovies = async (title) => {
const response = await fetch(`${API_URL}&s=${title}`);
const data = await response.json();
console.log(data.search);
}
useEffect(() => {
searchMovies('spiderman');
}, []);
return (
<div className="app">
<h1>MovieLand</h1>
<div className="search">
<input
placeholder="search for movies"
/>
/*https://react-icons.github.io/react-icons/icons?name=gi*/
<img
src={SearchIcon}
alt="search"
/>
</div>
</div>
);
}
export default App;
showing a search icon inside my search bar.
on the browser it displays 'SearchIcon' is not defined no-undef
There are different ways of doing this, I would either install #fortawesome/react-fontawesome and #fortawesome/free-solid-svg-icons and do it with that, or, the option I would prefer that consists in using inline styles, positioning the icon as a background of the input tag; it would be something like this:
import React, { useState } from "react";
import searchIcon from "path/to/search-icon.svg";
function SearchInput() {
const [searchTerm, setSearchTerm] = useState("");
return (
<div>
<input
type="text"
placeholder="Search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{
padding: "0.5rem 0.5rem 0.5rem 2rem",
background: `url(${searchIcon}) no-repeat`,
backgroundSize: "1.5rem",
backgroundPosition: "0.5rem center",
}}
/>
</div>
);
}
export default SearchInput;
This will create an input element with a search icon as its background, and the icon will be positioned inside the input at the center left of the input field.
You can adjust the position of the icon using the background-position property and you can adjust the size of the icon using the background-size property.
Related
In Semantic UI, a message can be visible
<Message visible>You can always see me</Message>
or hidden.
<Message hidden>You can't see me</Message>
I have a button that when clicked gets an API response, that then fills a Message with text. I only want to see the Message after clicking the button, because until then it is just an empty box at the bottom of the screen. How can I implement this in my function?
import React, { useState } from 'react';
import { Button, Header, Message} from 'semantic-ui-react'
export default function Writer() {
const [titleText, setTitleText] = useState('');
const getResponse = () => {
//Does Some Stuff
}).then((response) => {
setTitleText(response.data.choices[0].text)
})
return (
<div>
<Button onClick={getResponse}></Button>
<Message>
<Header
icon textAlign='center'
content={titleText}
/>
</Message>
</div>
)
}
I tried to set a variable
var visibility = 'hidden'
and set visibility = 'visible' inside the function, then writing <Message {visibility}? but it did not work. Any recommendations please?
In Semantic-UI-React the visible & hidden are boolean flags. So you need to pass in a Boolean value. & because you need it to be done based on titleText you can simply use the length property.
import React, { useState } from 'react';
import { Button, Header, Message} from 'semantic-ui-react'
export default function Writer() {
const [titleText, setTitleText] = useState('');
const getResponse = () => {
//Does Some Stuff
}).then((response) => {
setTitleText(response.data.choices[0].text)
})
return (
<div>
<Button onClick={getResponse}></Button>
<Message visible={titleText.length > 0} hidden={titleText.length === 0}>
<Header
icon textAlign='center'
content={titleText}
/>
</Message>
</div>
)
}
When contentEditable is set to true, only the element that is focused can be selected. I'm trying to make cells that function like they do in excel. I'd like to be able to edit the cell on a single click, otherwise I would just set contentEditable with state and select them as regular div elements. I thought about doing something with onMouseOut to change the state to false, but thet doesn't seem to work.
App component:
import { useState, useRef, useEffect } from "react";
import Cell from "./Cell";
export default function App() {
const testRef = useRef();
const [st, setSt] = useState(false);
useEffect(() => {
if (st) testRef.current.focus();
}, [st]);
return (
<div style={{ display: "flex" }}>
<Cell tabindex="1" />
<Cell tabindex="2" />
<Cell tabindex="3" />
</div>
);
}
Cell component:
import "./styles.css";
import { useState, useRef, useEffect } from "react";
export default function Cell() {
const [editing, setEditing] = useState(true);
const testRef = useRef();
const stopEditing = () => setEditing(false);
const startEditing = () => setEditing(true);
return (
<div>
<div
ref={testRef}
contentEditable={editing}
// onBlur={stopEditing}
// onMouseUp={stopEditing}
onMouseOver={startEditing}
style={{
display: "flex",
border: "1px solid #696969",
width: "100px",
height: "25px",
cursor: "cell",
margin: "2px"
}}
></div>
<p>{editing.toString()}</p>
</div>
);
}
https://codesandbox.io/s/unruffled-rain-i0v40g?file=/src/Cell.js:0-734
<div class = "div1" onmousedown = "selectFunction()">
function selectFunction() {
document.getElementByClassName("div1")[0].style.color = "red"; }
Maybe something like this? However, this will only work for one of the div's, try applying them to all the div's. This might not work, I'll edit it if it does not. (All this does it highlight the div red, probably won't work if you want to select multiple div's at once)
I have a simple Input type= file. I am capturing the the selected file in state. Once a file is selected and the clear button is clicked it does not clear the state. This causes {selectedFile.name} to throw an undefined error when the user clicks cancel during the next file selection.
Is there a way to make my clear button actually clear selectedFile state? or a way to handle the error so that a file can still be selected?
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import AddIcon from "#mui/icons-material/Add";
import { withStyles } from "#material-ui/core/styles";
import Fab from "#mui/material/Fab";
const styles = () => ({
root: {
boxSizing: "border-box",
margin: "0",
padding: "0"
},
textInput: {
textAlign: "center"
},
test: {
fontSize: "3rem"
}
});
const CampaignForm = props => {
const { classes } = props;
const [selectedFile, setSelectedFile] = useState();
const [isFileSelected, setIsFileSelected] = useState(false);
const handleClear = event => {
setIsFileSelected(false);
setSelectedFile("");
console.log(selectedFile.name);
};
const handleFileSelection = event => {
setSelectedFile(event.target.files[0]);
setIsFileSelected(true);
};
return (
<div className={classes.root}>
<h1 className={classes.textInput}>Text Campaign</h1>
<div className={classes.textInput}>
<label htmlFor='upload-csv'>
<input
style={{ display: "none" }}
id='upload-csv'
disabled={isFileSelected}
name='upload-csv'
type='file'
onChange={handleFileSelection}
/>
<Fab
color='primary'
size='small'
disabled={isFileSelected}
component='span'
aria-label='add'
variant='extended'>
<AddIcon /> Add CSV
</Fab>
</label>
<br />
{isFileSelected ? (
<div>
<br />
<button onClick={handleClear}>clear</button>
<p>{selectedFile.name}</p>
</div>
) : (
<p>No file added</p>
)}
</div>
</div>
);
};
CampaignForm.propTypes = { classes: PropTypes.object.isRequired };
export default withStyles(styles)(CampaignForm);
enter image description here
First You need to set the default null value to selectedFile state.
const [selectedFile, setSelectedFile] = useState(null);
Then, in handleClear Function set,
setSelectedFile(null);
and final the condition should be
{isFileSelected ? (
<div>
<br />
<button onClick={handleClear}>clear</button>
<p>{selectedFile.name}</p>
</div>
) : (
selectedFile === null && <p>No file added</p>
)}
[optional]:
the default file select event does not select the same file again, so if you need to allow the user to select the same file then add following property in the input tag:
onClick={(event) => {
event.target.value = null;
}}
you have to do, in handleClear function, im guessing that setSelectedFile(event.target.files[0]); is json object not string,
setSelectedFile({});
as you are setSelectedFile(""); setting string to it, string dont have .name only json have that
<p>{selectedFile.name}</p>
so "".name name would be undefined, which is correct, your fix would be this, hope it helps
const handleClear = event => {
setIsFileSelected(false);
setSelectedFile({});
console.log(selectedFile.name);
};
I have a google maps widget on my page with markers on it to represent specific locations. I have made it so that when you click on the marker, a tooltip will appear above it to show more information. I am using react tooltip. Here's my index.jsx
<GoogleMaps
bootstrapURLKeys={{ key: /* KEY */ }}
center={center}
zoom={zoom}
>
<ReactTooltip
id="google"
html
multiline
/>
{markers.map((marker) => (
<Marker
key={marker.key}
place={marker}
lat={marker.lat}
lng={marker.lng}
/>
))}
</GoogleMaps>
Here's my Marker.jsx
import React from 'react';
import MarkerWindow from "./MarkerWindow"
const Marker = ({ place }) => {
const tip =
<>
<MarkerWindow place={place}/>
</>;
return (
<>
<Wrapper
data-for="google"
data-event="click focus"
data-tip={tip}
/>
</>
)
};
export default Marker;
And then my MarkerWindow.jsx
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
const MarkerWindow = ({ place }) =>
(
<StyledSection>
<h3>${place.name}</h3>
<p>
${place.address}
<br />
${place.number}
<br />
</p>
</StyledSection>
);
const StyledSection = styled.div`
width: 18px;
height: 18px;
background-color: #e01414;
`;
MarkerWindow.propTypes = {
place: PropTypes.object.isRequired,
};
export default MarkerWindow;
But when I load the page, I get this:
How do I load custom components into ReactTooltip?
react-tooltip doesn't support components as the tooltip content, but accepts html strings.
You should use the data-html={true} prop to let the react-tooltip know that the value passed to data-tip is actually an HTML code.
Then you should provide the html of the tooltip content as a string.
So this should work:
const Marker = ({ place }) => {
const tip = `
<div style="width: 18px; height: 18px; background-color: '#e01414';" >
<h3>${place.name}</h3>
<p>
${place.address}
<br />
${place.number}
<br />
</p>
</div>
`;
return (
<>
<Wrapper
data-for="google"
data-event="click focus"
data-html={true}
data-tip={tip}
/>
</>
)
};
I converted your MarkerWindow component to an HTML string by inlining the styles from the styled-component.
However, if you are not limmited to use react-tooltip I suggest to use other packages that let you render react components for a tooltip content. Take a look at #tippyjs/react for example.
I have a search bar in a header component like the picture below. Once you click the search icon the search bar will appear and you can start searching. The idea here, is that once you click the icon again the text inside the search bar should be reset to an empty state. Once the icon in the header component is pressed the cleanSearch useEffect will be triggered. inside both console.logs we find that the state of input is set to ''. However the problem I currently have is that once I show the search bar again the old value is still residing in it. It seems that only the clearing state is not working here.
I also tried to give <StyledSearch> a value={input.value} and tried different ways to set and clean the state. What is going wrong here?
edit: I recreated the problem in this sandbox
https://codesandbox.io/s/adoring-mahavira-o1hyu
controlled input in SearchBar component
/** Search bar in header */
const SearchBar = props => {
const { isActive, cleanSearch } = props;
const [input, setInput] = useState({});
useEffect(() => {
if (cleanSearch) {
setInput({});
props.cleanSearchCallback(false);
}
console.log('cleanSearch', input);
}, [cleanSearch]);
console.log('cleanSearch outer', input);
/** controlled search input */
const handleInputChange = e => {
setInput({
...input,
[e.currentTarget.name]: e.currentTarget.value,
});
props.appbarSearch(...input, e.currentTarget.value);
};
return (
<StyledSearch
type="search"
placeholder="Type between 3 ~ 50 characters to find anything"
isActive={isActive ? 'visible' : 'hidden'}
name="searchbar"
onChange={handleInputChange}
/>
);
};
Well the answer was to add a ref inside the Search bar as seen in the code below (this is the workable example in codesandbox).
import React, { useRef } from "react";
const Search = () => {
const ref = useRef();
const clearValue = () => {
if (ref.current) ref.current.value = "";
};
return (
<div>
<input ref={ref} name="search" />
<button style={{ width: "50px", height: "50px" }} onClick={clearValue} />
</div>
);
};
export default Search;