SOLUTION: as #prasanth sugested me, I created a fake dropdown, a placeholder.
Both the fake and the real dropdown shares a
style={{"display":countryChange?"":"none"}}
obviously the real one is inverted with the fake one. Once i ping the api, I hide the real one and show the fake one. Once the api returns with value, i write the state so the fake disapears. Worked like a charm.
I'm new to react, and trying to make a dynamic dropdown based on an api call. I have a local api in "/avaliable_countries" which returns {countries:"Brasil" and "United States"}. I want those two fields to create the <options> dynamcially, and it is almost working as intended.
The problemis: In the first click, I got this weird arrows. If I click out/again or two times, then it becomes normal.
no click:
first click, weird arrows(and using the weird arrows can navigate between the two countries):
Clicking in/out or two times in a row, becomes the desired output:
Without any CSS(weird arrows still here):
The code:
import React,{useState} from 'react';
import {Link} from 'react-router-dom';
import './styles.css';
import api from '../../services/api';
export default function Signup(){
var [countriesObj, setCountriesObj] = useState(<option>Select your country</option>)
async function getAvaliableCountries(){
setCountriesObj();
try{
const response = await api.get(
'avaliable_countries','',
{headers: {
'Content-Type':"application/json",
}
});
window.arrayOfCountries = response.data.countries ;
let countriesList = (window.arrayOfCountries.map((data) =>
<option>
{data}
</option>)
);
setCountriesObj(countriesList);
}catch(err){
alert('Error obtaining the list of countries.')
}
}
return(
<div className="wrapper">
<div id="formContent">
<h2 className="inactive underlineHover">
<Link to="/">Sign In</Link>
</h2>
<h2 className="active">
Sign Up
</h2>
<form>
<select
onClick={getAvaliableCountries}
name="animal"
className="form-control">
{countriesObj}
</select>
</form>
<div id="formFooter">
</div>
</div>
</div>
);
}
You could do like this .Component use with in array not a good practise.so extract the component with Array#map on render .And dont forget use the key on map child options
Updated :
load the array on component mount instead of click . try this useEffect with in react
Demo code
import React,{useState,useEffect} from 'react';
import {Link} from 'react-router-dom';
import './styles.css';
import api from '../../services/api';
export default function Signup() {
var [countriesObj, setCountriesObj] = useState(['select'])
async function getAvaliableCountries() {
setCountriesObj();
try {
const response = await api.get(
'avaliable_countries', '', {
headers: {
'Content-Type': "application/json"
}
}
);
window.arrayOfCountries = response.data.countries;
let countriesList = response.data.countries
setCountriesObj(countriesList);
} catch (err) {
alert('Error obtaining the list of countries.')
}
}
useEffect(()=>{
getAvaliableCountries()
},[])
return(
<div className="wrapper">
<div id="formContent">
<h2 className="inactive underlineHover">
<Link to="/">Sign In</Link>
</h2>
<h2 className="active">
Sign Up
</h2>
<form>
<select name="animal" className="form-control">
{countriesObj.map(data => (
<option key={data}>{data}</option>
))}
</select>
</form>
<div id="formFooter">
</div>
</div>
</div>
);
}
This is actually not React related and you can use simple CSS to remove the arrow:
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none; /* Remove default arrow */
background-image: url(...); /* Add custom arrow */
}
For more information you can see the original answer here: How do I style a dropdown with only CSS?
Kindly check your css and there must some css like "content: '<>';" which is crreating issue for this type of style.
It's not because of react and it's css issue so kindly check css (style.css) of select.
Related
i'm a react beginner and I'm struggling with the refresh of the components.
In this case, I have a GET request to an API triggering in a useEffect hook with no dependencies on my App.js. Of course, this is working just fine when my app just starts. However, I need it to trigger again after certain events ocurre, like an Onclick event in a button, and a OnSubmit event in a form, in order to re render the updated table component where the API data is displayed.
What is the best way to do this?
I thought about just calling the fetch function again whenever I need to update the data, but I don't know if that's the way to go.
Then, I currently have this workaround function to force the reload of the entire page after the events trigger, but i'm pretty sure this is not proper either:
const refresh = () =>{
window.location.reload(false);
}
I've been also tweaked the dependencies in the use effect (where the fetch happens) a little bit, because I'm feeling like the solution is there, but I had only bad results, like infinite loops.
Finally guys, I'll post an overview pic of my App code. Have in mind that I need to do the refresh in the next components: OrdenPago y Grid.
import { useState, useEffect } from 'react';
import { OrdenPago } from './OrdenDePago';
import EstadoCvus from './EstadoCvus';
import Grid from './Grid';
import axios from 'axios';
export const App = () => {
const [ops, setOps] = useState({ ordenesPago: [] });
useEffect( () => {
axios.get("http://cpawautojava:1400/consultaOrdenesPago")
.then(response => {
setOps(response.data);
console.log(response.data);
}).catch((error) => { console.log(error) })
}, [])
return (
<div className="container">
<div className='row'>
<div className='col-12'>
<div className='text-white py-2' style={{ backgroundColor: "#414BB2", height: "40px" }} >
<h1 className='text-center lead fw-bold'>Gestión de OPs</h1>
</div>
</div>
</div>
<div className='row mt-3' >
<div className='col-6 d-flex justify-content-center'>
<OrdenPago />
</div>
<div className='col-6 form1' >
<EstadoCvus />
</div>
</div>
<div className='row'>
<div className='col-12' >
<Grid ops={ops} />
</div>
</div>
</div>
);
}
Thanks in advance for your help.
Rodrigo.
I'm making a blog where I need a button to appear only if a user selects a specific story, if the user selects other reports, the button should not appear.
These reports are in markdown file.
I thought of using a conditional rendering with a state and use
{
Show && (<div><div/>)
}
Here's the code where the commented part what was trying to do something
import markdownStyles from './markdown-styles.module.css'
import Show_button_1 from './show_button_1'
export default function PostBody({ content }) {
/*const retornarPagina=()=>{
if(content==_posts.receita_0.md){
return
<Show_button_1/>
}
*/
return (
<div className="max-w-2xl mx-auto">
<div
className={markdownStyles['markdown']}
dangerouslySetInnerHTML={{ __html: content }}
/>
<Show_button_1/>
</div>
)
}
I tried to do it this way but it didn't work (03/30/2022)
import React, {useState} from 'react'
import markdownStyles from './markdown-styles.module.css'
import Show_button_1 from './show_button_1'
export default function PostBody({ content }) {
const [Show, setShow] = useState(false);
const retornarPagina=()=>{
if(content===_posts.receita_0.md){
{setShow(true)}
}
}
return (
<div className="max-w-2xl mx-auto">
<div
className={markdownStyles['markdown']}
dangerouslySetInnerHTML={{ __html: content }}
/>
{Show && (<Show_button_1/>)}
</div>
)
}
I'm not sure I understood the question correctly, but one crutch I used to conditionally render components was
{
Show ? (<div><div/>) : (<></>) //doesn't render anything
}
This should work for you.
{content === '_posts.receita_0.md' && <Show_button_1/> }
If you need multiple lines:
{content === '_posts.receita_0.md' && (
<Show_button_1/>
)}
you won't be able to use conditional rendering on a full file, you may want to consider refactoring your code to send a title of the markdown file through props as well. so you would do something like so:
<MyComponent content={document.markdown} title={document.title}/>
Then you can easily do
{props.title === 'some_title' && <Show_button_1/> }
I have this 2 states, from 2 different api calls
one is 'movieList' and the other one is 'search', Both are array of movies.
movieList is automatically rendered since it is the search for popular movies and it corresponds that the user is shown as soon as he opens the page, in the navbar I have an input attached to a state called search and it saves an array of movies that match the name in it ... try to use a conditional with the following logic, if search exists, maps search, otherwise map movieList.
but it seems I don't know how to do it correctly. If someone can give me a hand in how to do it, it would help me a lot, thank you very much! here I leave the code
import { useSelector } from 'react-redux'
import { getAllMovies } from '../../features/movieSlice'
import MovieCard from '../MovieCard/MovieCard';
const MovieListing = ({ movieList, search }) => {
return (
<div className='' >
<div className=''>
<div className='my-20 mx-15 flex flex-wrap justify-around items-center' >
{
movieList.map((movie)=>(
<MovieCard {...movie} key={movie.id} />
))}
</div>
</div>
</div>
)
}
export default MovieListing```
To do a conditional render you can try use a ternary operator:
<div className='' >
<div className=''>
<div className='my-20 mx-15 flex flex-wrap justify-around items-center' >
{
search ? search.map((searchItem) => <MapsSearch {...search}/> :
movieList.map((movie) => (<MovieCard {...movie} key={movie.id}/>))
}
</div>
</div>
</div>
(You'll just need to modify the mapping of search and what it returns as I'm not sure what type search is)
I have a react page builder, I am displaying user-created pages using dangerous HTML now I want when the user clicks a button preview to open this page on a new window.
Here is my component to display user pages
import React, { useState, useEffect} from "react";
import api from "../utils/api";
function MyPages() {
const [MyPagesList, setMyPagesList] = useState();
const getMyPages = async () => {
try {
const response = await api.get("/pages");
setMyPagesList(response.data.data);
} catch (error) {}
};
useEffect(() => {
getMyPages();
}, []);
return (
<div className="all-mypages">
<div className="all-mypages__cards">
{MyPagesList && MyPagesList.map(function (data, id) {
return (
<div className="mypages-card" key={id}>
<a className="mypages-card__link">
<div className="mypages-card__content"
dangerouslySetInnerHTML={{__html: data.attributes.html}}></div>
</a>
<button className="preview " onClick={()=>history.push(`/mypages/preview/${data.attributes.html}`)>Preview</button>
</div>
);
})}
</div>
</div>
);
}
export default MyPages;
When user clicks preview button here is what I get
My solution is not working and I am out of ideas, what do I need to do to solve this issue?
The result is correct, because you are appending the html to /mypages/preview/. If you want the data.attributes.html ( which is the user html content ) to be displayed on a new page then:
Create another React component which looks for this html content from localStorage redux
When clicked on the preview button open a new page with url in react router pointing to this component
This component on load will get the localStorage html content and pass it to its dangerouslySetInnerHtml and display it.
i dont know if this is possible but at the moment when user click from select options it will take to that specific url, my point is can we have search functionality in 'Search...' so user could search from hundreds of option and then choose it and click the button and that button should also take to that same 'onChange' address. You can also suggest other options, even without select but functionality must be same , here is my code:
import "antd/dist/antd.css";
import { Select } from "antd";
// import { Link, useHistory, useRouteMatch, useParams } from "react-router-dom";
function EventsSection() {
// const history = useHistory();
const { Option } = Select;
// const changeHandler = (id) => {
// history.push(`/customer/${id}`);
// };
return (
<div>
{/* when found in search i want this button take to 'onChange' address also*/}
<button>click me when found in search</button>
<Select
style={{ width: 200 }}
placeholder="Search..."
mode="multiple"
open={true}
listHeight={128}
// onChange={changeHandler}
>
<Option value="1">Not Identified</Option>
<Option value="2">Closed</Option>
<Option value="3">Communicated</Option>
<Option value="4">Identified</Option>
<Option value="5">Resolved</Option>
<Option value="6">Cancelled</Option>
</Select>
</div>
);
}
export default EventsSection;
The first part is done.
Check at CodeSanbox.
The second part is still unclear to me.
Exactly this part
and then that button can be cliked which should take user to that
’onChange’