ReactJS Conditional Rendering - else if doesn't work - javascript

I'm in the stage of learning JS and React and I'm not sure why else if doesn't work in the code below. Anyone can help me?
function Item({ name, isPacked }) {
if (isPacked) {
return (
<li className="item">
{name} {isPacked && " ✔"}
</li>
);
} else if (!isPacked) {
return (
<li className="item">
{name} {isPacked && " ❌"}
</li>
);
}
}
export default function PackingList() {
return (
<section>
<h1>Sally Ride's Packing List</h1>
<ul>
<Item isPacked={true} name="Space suit" />
<Item isPacked={true} name="Helmet with a golden leaf" />
<Item isPacked={false} name="Photo of Tam" />
</ul>
</section>
);
}

Try like this:
function Item({ name, isPacked }) {
return (
<li className="item">
{`${name} ${isPacked ? "✔" : '❌'} `}
</li>
);
}

you actually tested if the isPacked true or false so try this code:
function Item({ name, isPacked }) {
return (
<li className="item">
{name} {isPacked ? "✔" : "❌" }
</li>
);
}
{isPacked ? "✔" : "❌" } so this line of code is equal to:
if(isPacked == true){
return "✔";
}else{
return "❌";
}
You can get some helpful examples Here https://reactjs.org/docs/conditional-rendering.html.

Related

Cannot access updated value

Hello Am i need of some assistance here am stuck,tried to serach for solution on SO but cant find a solution ,Am learning react so decided to create a todo app.However i have been stuck when it comes to crossing off completed tasks. when i add a task i have a variable called tasks which basically is an object containing all the tasks in the following fomart:
enter image description here
Inside my app i have the following snippet of code
const FILTER_MAP = {
all_items:() => true,
Active: task => !task.completed,
Completed: task => task.completed
};
const FILTER_NAMES = Object.keys(FILTER_MAP);
function App(props) {
const [tasks, setTasks] = useState(props.tasks);
const [filter, setFilter] = useState('all_items');
function addTask(name) {
const newTask = {id: "todo-" + nanoid(),name: name, completed:false}
setTasks([...tasks, newTask]);
}
function toggleTaskCompleted(id) {
const updatedTasks = tasks.map(task => {
// if this task has the same ID as the edited task
if(id === task.id) {
// use object spread to make a new object
// whose `completed` prop has been inverted
return {...task,completed: !task.completed}
}
return task;
})
setTasks(updatedTasks);
}
function clearCompletedTasks(){
const completed = tasks.filter(task => task.completed === false)
setTasks(completed);
}
const taskList = tasks
.filter(FILTER_MAP[filter])
.map(task => (
<Todo
id={task.id}
name={task.name}
completed={task.completed}
key={task.id}
toggleTaskCompleted={toggleTaskCompleted}
clearCompletedTasks={clearCompletedTasks}
/>
));
const filterList = FILTER_NAMES.map(name => (
<FilterButton
key={name}
name={name}
isPressed={name === filter}
setFilter={setFilter}
/>
));
const tasksNoun = taskList.length !== 1 ? 'items' : 'items';
const headingText = `${taskList.length} ${tasksNoun} left`;
return (
<div>
<header>
<h1 id="pageTitle">Todo</h1>
<div className="container">
<div className="main">
<section className="tasklist">
<Form addTask={addTask}/>
<ul className="listItems">
<li className={`todo-item ${ tasks.completed ? "completed" :'' }`} >{taskList}</li>
</ul>
</section>
</div>
<div className="footer">
<div className="footer-list">
<ul>
<li id="items">{headingText}</li>
<li id="all-items">{filterList[0]}</li>
<li id="active">{filterList[1]}</li>
<li id="completed">{filterList[2]}</li>
<li id="clear" onClick={clearCompletedTasks}>XClear Completed</li>
</ul>
</div>
</div>
</div>
</header>
</div>
);
}
export default App;
Todo
export default function Todo(props){
return (
<li>
<div className="todo">
<label htmlFor={props.id}>
{props.name}
</label>
<input id={props.id}
type="checkbox"
defaultChecked={props.completed}
onChange={() =>
props.toggleTaskCompleted(props.id)}
/>
</div>
</li>
);
}
Problem
When i click on checkbox to indicate the task is done i can see that the value in completed is updating to true as show below
enter image description here
However when i try to evaluate and apply the following css its not working.
<li className={`todo-item ${ tasks.completed ? "completed" :'' }`} >{taskList}</li>
How can i implement this so that "completed" style class is used when the state of completed value changes to true.Thank you
The problem is that you use a const to store an array which gets changed.
The correct thing to do would be the following:
<ul>{tasks
.filter(FILTER_MAP[filter])
.map(task => (
<li class={`todo-item ${ task.completed ? "completed" :'' }`}>
<Todo
id={task.id}
name={task.name}
completed={task.completed}
key={task.id}
toggleTaskCompleted={toggleTaskCompleted}
clearCompletedTasks={clearCompletedTasks}
/></li>
))}
</ul>
This looks like a case of stale state. When your function closes over an old state (think closures), then whenever called in future it has access to the old state itself. Similar question
Check if moving your {tasksList} code inside the return method helps:
<li className={`todo-item ${ tasks.completed ? "completed" :'' }`} >{
tasks
.filter(FILTER_MAP[filter])
.map(task => (
<Todo
id={task.id}
name={task.name}
completed={task.completed}
key={task.id}
toggleTaskCompleted={toggleTaskCompleted}
clearCompletedTasks={clearCompletedTasks}
/>
));}</li>

If-else statement in .map loop in JSX

Instagram clone:
I want to check if I follow my follower then display <button>unfollow</button> or if not display <button>follow</button>
var IfollowAndHeFollowMe;
myfollowers.map(follower => {
return(
<div>
<div>{follower.userName}</div>
{ IfollowAndHeFollowMe =
myfollowings.filter((following) => following.userName == follower.userName)
}
// this doesn't work
{ IfollowAndHeFollowMe.length > 0 ? return( <button>unfollow</button>): return(<button>follow</button>) }
// and this also doesn't work
{ return IfollowAndHeFollowMe.length > 0 ? <button>unfollow</button> : <button>follow</button>}
</div>
)
})
//https://instagram-app-clone.netlify.app/ --- just for phone ---
JSX Code inside {} should be written as statements.
https://reactjs.org/docs/conditional-rendering.html
const followers = ['John', 'Hanna'];
function RenderMap() {
return (
<React.Fragment>
{followers.map(follower => (
<div>
<span>{follower}</span>
{followers.length > 0 ? (
<button>unfollow</button>
) : (
<button>follow</button>
)}
</div>
))}
</React.Fragment>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
// now dont have errors but its allways display button with follow text
{Data[2][0].followers.map(follower => {
idFollowers++;
return (
<div className="follower" id={idFollowers} >
<img src={follower.profilna} className="profilnaFollower" alt="" />
<div className="userInfoFollower">
<h3>{follower.userName}</h3>
<p>{follower.name}</p>
</div>
{dbFollow = Object.entries(Data[2][0].following).filter(following => following.userName == follower.userName)}
{dbFollow.length > 0 ? (<button>unfoldasdaslow</button>) : (<button>fodsadsllow</button>)}
</div>
)
})}
</div>

How can i create hyperlinks within the map method?

I have an array of files and I want certain ones to be displayed and hyperlinked. I'm using the map method and when only 1 file displays, it links properly. I need some help with the syntax when multiple files must be displayed.
render() {
const mappings = {
'P1011': 'http://192.168.191.128:8080/Pickering-P1011-May-Verified_Results5.xls',
'P1511': 'http://192.168.191.128:8080/PNGS-1511-Verified_Results_2.xls',
'P1711': 'http://192.168.191.128:8080/PNGS-P1711_Verified_Results_3.xlsx',
'P1911': 'http://192.168.191.128:8080/PLGS_Unit_1-PL1911_VerifiedResults2.xlsx',
}
if (this.props.channelSelectedData.length >= 1){
return(
<div className="channel-detail-box">
<p>Outages:
<a href={mappings[this.props.channelSelectedData.map(inspection => {
return inspection.outage
})]}>
{this.props.channelSelectedData.map(inspection => {
return inspection.outage + ' '
})}</a>
</p>
</div>
)
}
else {
return (
<div>
<p>No data found</p>
</div>
)
}
}
}
Is this what you are looking for ?
render() {
const mappings = {
'P1011': 'http://192.168.191.128:8080/Pickering-P1011-May-Verified_Results5.xls',
'P1511': 'http://192.168.191.128:8080/PNGS-1511-Verified_Results_2.xls',
'P1711': 'http://192.168.191.128:8080/PNGS-P1711_Verified_Results_3.xlsx',
'P1911': 'http://192.168.191.128:8080/PLGS_Unit_1-PL1911_VerifiedResults2.xlsx',
}
const { channelSelectedData } = this.props
if (channelSelectedData.length === 0) {
return <div>
<p>No data found</p>
</div>
}
return <div className="channel-detail-box">
<p>Outages: {channelSelectedData.map(({ outage }) => <a href={mappings[outage]}>{outage}</a>)}</p>
</div>
}
const mappings = {
'P1011': 'http://192.168.191.128:8080/Pickering-P1011-May-Verified_Results5.xls',
'P1511': 'http://192.168.191.128:8080/PNGS-1511-Verified_Results_2.xls',
'P1711': 'http://192.168.191.128:8080/PNGS-P1711_Verified_Results_3.xlsx',
'P1911': 'http://192.168.191.128:8080/PLGS_Unit_1-PL1911_VerifiedResults2.xlsx',
};
if (!channelSelectedData || channelSelectedData.length <= 0) {
return (
<div>
<p>No data found</p>
</div>
);
}
const links = channelSelectedData.map(({ outage }) => (
<a href={mappings[outage]}>{outage}</a>
));
return (
<div className="channel-detail-box">
<p>Outages: {links}</p>
</div>
);
If I am understanding the rest of your question correctly, I believe your issue is just using map at the incorrect point. What map does is returns an array of values which in this case would be an array of applicable tags.
render() {
const mappings = {
'P1011': 'http://192.168.191.128:8080/Pickering-P1011-May-Verified_Results5.xls',
'P1511': 'http://192.168.191.128:8080/PNGS-1511-Verified_Results_2.xls',
'P1711': 'http://192.168.191.128:8080/PNGS-P1711_Verified_Results_3.xlsx',
'P1911': 'http://192.168.191.128:8080/PLGS_Unit_1-PL1911_VerifiedResults2.xlsx',
}
if (this.props.channelSelectedData.length >= 1){
return(
<div className="channel-detail-box">
<p>Outages:
<>
{
this.props.channelSelectedData.map(chanel=>{
return (
<a href={mappings[chanel]}>
{chanel+' '}
</a> )
})
}
</>
</p>
</div>
)
}
else {
return (
<div>
<p>No data found</p>
</div>
)
}
}

react-responsive-carousel messed up

I've read the documentation, I don't know why it's working but it's messed up. Here's my code :
function CarouselItem(props) {
const { post } = props
return (
<React.Fragment>
<div>
<img src={`http://localhost:5000/image/${post.foto}`} />
<p className="legend">{post.judul}</p>
</div>
</React.Fragment>
)
}
function NewsItem(props) {
const { posts } = props.post
let content = posts.map(item => <CarouselItem key={item._id} post={item} />)
return (
<div>
<Carousel showThumbs={false}>{content}</Carousel>
</div>
)
}
It turns out like this :
Use this in the first line of your .js file:
import 'react-responsive-carousel/lib/styles/carousel.min.css';

Function doesn't do anything

Basically, I am sending an array of objects into my function as a parameter, but the function doesn't do anything. When I want to print out my array of objects, I can show all items on the console, however, I cannot render them.
renderComment() function doesn't work or doesn't return anything. Also you can take a closer look at my render method, you will see that commented code to print out the expected output of renderComment in the console.
class DishDetails extends Component {
renderDish(dish) {
if (dish) {
return (
<div>
<Card className="col-12 col-md-5 m-1">
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardBody>
<CardTitle>{dish.name}</CardTitle>
<CardText>{dish.description}</CardText>
</CardBody>
</Card>
</div>
)
} else {
return (
<div></div>
)
}
}
renderComments(comments) {
comments.map(comment => {
return (
<li key={comment.id}>
<p>{comment.comment}</p>
<p>{comment.author}</p>
</li>
)
})
}
render() {
const selected = this.props.selectedDish;
/* if(selected) {
this.props.selectedDish.comments.map(comment => {
console.log(comment.comment)
})
} */
return (
<div>
{selected &&
<div>
{this.renderDish(this.props.selectedDish)}
{this.renderComments(this.props.selectedDish.comments)}
</div>
}
</div>
)
}
}
export default DishDetails
The renderComment function does not return anything because there is no return statement in the function. There is a return in the map (which is still required), but that is not the return for the function.
To fix this, add a return at the top of renderComment, like this:
renderComment(comments) {
return comments.map(comment => {
return (
<li key={comment.id}>
<p>{comment.comment}</p>
<p>{comment.author}</p>
</li>
)
}
}

Categories

Resources