I'm fetching data and showing under a search input
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try{
const response = await axios("/posts");
setAPIData(response.data);
setIsLoading(false);
} catch(error) {
setError(true);
console.error(error);
}
};
fetchData();
}, []);
console.log(APIData)
The user types in the search input and it show the results and if there is no results it shows a message "No Results Found!" .. the problem is this message is showing by default which is a bad UI, I only want this message to show if there is no result and by default shows the APIData
{filteredResults && filteredResults.length > 0 ? (
filteredResults.map((post) => {
return (
<div className="card" key={post._id}>
<div className="card-content">
<Link to={`/post/${post._id}`} className="link">
<h2 className="results-title">
{post.title}
</h2>
<ol className="card-username">
{post.username}
</ol>
</Link>
</div>
</div>
)
})
) : (
<h1>No results found!</h1>
)}
I didn't if I should another useState for it or there another way !
You can use isLoading state for conditional rendering:
{isLoading ? (
<h1>Loading...</h1>
) : (
<>
{filteredResults && filteredResults.length > 0 ? (
filteredResults.map((post) => {
return (
<div className="card" key={post._id}>
<div className="card-content">
<Link to={`/post/${post._id}`} className="link">
<h2 className="results-title">{post.title}</h2>
<ol className="card-username">{post.username}</ol>
</Link>
</div>
</div>
);
})
) : (
<h1>No results found!</h1>
)}
</>
)}
Remember to set isLoaidng state to false if the request fails:
try {
// ...
} catch(error) {
// ...
} finally {
setIsLoading(false); // <==
}
Related
How to pass this warning?
Code
const Main = (header, navigation) => {
return (
<>
<div>
{navigation !== false && <Navigation />}
</div>
</>
)
}
i tried this but still have the same warning
<Main navigation>
....
</Main>
Console output true
<Main navigation={true}>
....
</Main>
Console output true
<Main navigation={+true}>
....
</Main>
Console output 1
<Main>
....
</Main>
Console output undefined
use this code:
const Main = (header, navigation) => {
if (navigation !== false) return <Navigation />
return <></>
}
Try this:
const Main = (header, navigation) => {
return (
!!navigation ? <Navigation />:<></>
)
}
After receiving data from the DB server, you try to render it, but the console log shows the data, but the component is not rendered. What's the reason?
useEffect(() => {
readRequest().then(setTodos);
console.log()
}, []);
return (
<div className="App">
{todos.map((todo) => {
console.log(todo);
console.log(todo.text);
<div key={todo._id}>
{todo.text}
{`${todo.completed}`}
</div>
})}
<p>dfdf</p>
</div>
);
The picture is a screen capture.
Your .map callback does not return anything.
Change the { to (:
return (
<div className="App">
{todos.map((todo) => ( // <-- here
<div key={todo._id}>
{todo.text}
{`${todo.completed}`}
</div>
))}
<p>dfdf</p>
</div>
);
Or use the return keyword.
return (
<div className="App">
{todos.map((todo) => {
return (<div key={todo._id}>
{todo.text}
{`${todo.completed}`}
</div>);
})}
<p>dfdf</p>
</div>
);
The problem:
I want to show a (no results found) after doing a search and didn't found anything, I know that I should handle errors but I didn't know how! Beginners thing.
The Code:
first I fetched the data, then I settled as APIData, then when user is typing it start to filter the results, but i want to show a (no results found).
export default function SearchInput() {
const [APIData, setAPIData] = useState([]);
const [searchInput, setSearchInput] = useState('');
const [filteredResults, setFilteredResults] = useState([]);
const [error, setError] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
const fetchData = async () => {
setError(false);
setIsLoaded(true);
try{
const response = await axios("/posts");
setAPIData(response.data);
} catch(error) {
setError(true);
console.error(error);
}
setIsLoaded(false);
};
fetchData();
}, []);
console.log(APIData)
const searchItems = (searchValue) => {
setSearchInput(searchValue)
if (searchInput !== '') {
const filteredData = APIData.filter((post) => {
return Object.values(post).join('').toLowerCase().includes(searchInput.toLowerCase())
})
setFilteredResults(filteredData)
}
else{
setFilteredResults(APIData)
}
}
return (
<div style={{ padding: 20 }}>
<OutlinedInput
className="SearchInput"
placeholder='Search...'
onChange={(e) => searchItems(e.target.value)}
endAdornment={
<InputAdornment>
<SearchIcon />
</InputAdornment>
}
/>
<div style={{ marginTop: 20 }}>
{searchInput.length > 0 ? (
filteredResults.map((post) => {
return (
<div className="card" key={post._id}>
<div className="card-content">
<Link to={`/post/${post._id}`} className="link">
<h2 className="results-title">
{post.title}
</h2>
<ol className="card-username">
{post.username}
</ol>
</Link>
</div>
</div>
)
})
) : (
APIData.map((post) => {
return (
<article className="card" key={post._id}>
<div className="card-content">
<Link to={`/post/${post._id}`} className="link">
<h2 className="card-name">
{post.title}
</h2>
<ol className="card-username">
{post.username}
</ol>
</Link>
</div>
</article>
)
})
)}
</div>
</div>
I have implemented a simple drag and drop code here below using react-beautiful-dnd. The frontend alone works perfectly fine, however, when I tried to connect this with the backend the items in the droppable context are unable to be dragged. That is, I am unable to drag the items within the column and also between columns. Further, I am unable to figure out how to pass the index of the elements in the mongoDb database.
The code I used is here below
projectsDashboard.js
function ProjectsDashboard() {
const handleDragEnd = ({destination, source}) => {
if (!destination) {
return
}
if (destination.index === source.index && destination.droppableId === source.droppableId) {
return
}
// Creating a copy of item before removing it from state
const itemCopy = {...state[source.droppableId].items[source.index]}
setState(prev => {
prev = {...prev}
// Remove from previous items array
prev[source.droppableId].items.splice(source.index, 1)
// Adding to new items array location
prev[destination.droppableId].items.splice(destination.index, 0, itemCopy)
return prev
})
}
const dispatch = useDispatch();
useEffect(() => {
dispatch(getStages());
},[dispatch]);
const { stage } = useSelector(state => state.stage);
var formattedArray = stage.map(item => Object.keys(item).map(i => item[i]));
console.log(formattedArray)
return (
<DragDropContext onDragEnd={handleDragEnd}>
{_.map(state, (data, key) => {
return(
<div key={key} className={"column"}>
{console.log(key , "KEY")}
<ProjectWrapper className="border">
<h3 className="title">{data.title}</h3>
</ProjectWrapper>
<Droppable droppableId={key}>
{(provided, snapshot) => {
return(
<div>
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={"droppable-col"}
>
<hr className="line" style={{opacity: 10 }}></hr>
{stage.map(stages=>{
if(stages.status == key)
return(
<Draggable key={stages._id}
//index={index}
draggableId={stages._id} className="drag">
{(provided, snapshot) => {
console.log(snapshot)
return(
<div
className={`item ${snapshot.isDragging && "dragging"}`}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
{/* card name */}
<button className="stageDetails" style={{padding: "0",border: "none", background: "none"}}>
{stages.stageName}
</button>
<DeleteOutlinedIcon className="delete" />
</div>
)
}}
</Draggable>
)
})}
{provided.placeholder}
</div>
</div>
)
}}
</Droppable>
</div>
)
})}
</DragDropContext>
</div>
);
};
export default ProjectsDashboard;
{middleMenu.map((column) => {
return (
<div className="row">
column.map((item) => {
const { title, image, path } = item;
return (
<ul className="footer-collections">
<MenuLinks title={title} image={image} path={path} />
</ul>
);
})
</div>
);
})}
Does anyone know what the solution is? My first time using 2D Arrays
use :
<div className="row">
{column.map((item) => {
const { title, image, path } = item;
return (
<ul className="footer-collections">
<MenuLinks title={title} image={image} path={path} />
</ul>
);
})}
</div>