How to make my functional Post component have certain linkable properties? - reactjs

I'm new to React and haven't learned how to use databases and other functions as of yet and this is my first major learning React project. I'm trying to make my functional Post component link/route to a /profile/uniqueTweetId. Here is my Post component, to show you how I have set it up.
function Post({displayName,username,verified,text,image,avatar,comments,shares,likes,twitterId}) {
return (
<div className = "post">
<div className = "post__avatar">
<Avatar src={avatar} />
</div>
<div className = "post__body">
<div className = "post__header">
<div className = "post__headerText">
<h3>
{displayName} {""}
<span className = "post_headerSpecial">
{verified && <VerifiedUserIcon className="post__badge" />} #
{username}
</span>
</h3>
</div>
<div className = "post__headerDescription">
<p>{text}</p>
</div>
<img src= {image} alt= "" />
<div className = "post__footer">
<span className ="post__chatSpan"> <ChatBubbleOutlineIcon className = "post__chatStyling" fontSize="small" onClick={() => setCommentCount(commentCount + 1)} />
<span className = "post__chatFormating">{comments + commentCount} </span>
</span>
<span className ="post__repeatSpan"> <RepeatIcon className = "post__repeatStyling" fontSize="small" onClick={() => setRepeatCount(repeatCount + 1)} />
<span className = "post__repeatFormating">{shares + repeatCount}</span>
</span>
<span className ="post__favoriteSpan"> <FavoriteBorderIcon className = "post__favoriteStyling" fontSize="small" onClick={() => setLikeCount(likeCount + 1)} />
<span className = "post__favoriteFormating">{likes + likeCount}</span>
</span>
<PublishIcon fontSize="small" />
</div>
</div>
</div>
</div>
)
}
export default Post;
The problem arises when I render, the Post in my functional Feed component.
function Feed() {
return (
<Router>
<div className= "feed">
<Switch>
</Switch>
{/* Header */}
<div className= "feed__header">
<h2>Home</h2>
</div>
{/* TweetBox */}
<TweetBox />
{
listOfPosts.map(function (post) {
return (
< Post
displayName= {post.displayName}
username= {post.username}
verified= {post.verified}
text= {post.text}
avatar = "blah"
image = "blah"
comments = {post.comments}
shares = {post.shares}
likes = {post.likes}
twitterId ={post.twitterId}
/>
);
})
}
</div>
</Router>
)
}
export default Feed;
which listOfPosts is my array of hard coded "Post" prop variables that I'm currently looping through to render each post, so that in the future I could push the posts inside the array into a database when I'm ready. I'm struggling because I don't understand how to use React router in this context, because if I use Link inside the map function, All the props become a link, and I lose the functionality of my counters. I was hoping for ideas on how to attack this problem and to make my components work like an actual twitter post. Sorry for the long post it's my first StackOverflow question. Thank you again, any help is greatly appreciated!

Related

How to pass state properties from component to component

I am currently learning React and I am trying to create a basic todo list app. I am facing an issue in the understanding of how passing data from component to component.
I need that when I add a task in the modal of my home component it gets added in the "pub" state of my public task component in order for the task to be rendered.
I joined the code of both components,
Hope someone can help me :)
function PublicTask (){
const [pub,setPub] = useState([{id: 1, value : "test"},{id: 2, value : "test2"}]);
function ToDoPublicItem() {
const pubT = pub.map(value =>{
return(
<div className= 'pubTask-item'>
<li>{value.value}</li>
</div>
)
});
return(
<div>
<div>
{pubT}
</div>
</div>
);
}
return(
<div className= 'item-container'>
<h2 style={{color:'white'}}>Public Tasks</h2>
<ToDoPublicItem/>
</div>
);
}
export default PublicTask;
function Home() {
const [show,setShow] = useState(false);
const [pubTask,setPubTask] = useState([]);
function openModal() {
setShow(true);
}
function Modal(){
const[textTodo, setTextTodo] = useState('')
const addItem = () => {
const itemTopush = textTodo;
pubTask.push(itemTopush);
}
return(
<div className='modal'>
<div className = 'modal-title'>
<h2>ADD A TODO</h2>
<hr></hr>
</div>
<div className= 'modal-body'>
<input type='text' onChange = {(e) => setTextTodo(e.target.value)}/>
<input type="checkbox" id="pub" value ='public'/>
<label Htmlfor="pub">Public</label>
<input type="checkbox" id="priv" value= 'private '/>
<label Htmlfor="riv">Private</label>
<hr></hr>
<Button id='button-add' size='large' style={{backgroundColor : 'white'}} onClick={()=> addItem()}>ADD</Button>
<hr></hr>
<Button id='button-close' size='large' style={{backgroundColor : '#af4c4c'}} onClick= {()=> setShow(false)} >CLOSE</Button>
</div>
</div>
)
}
return(
<div>
<h1 style={{textAlign:'center'}}>You are logged in !</h1>
<div>
<button id='button-logout' onClick = {() => firebaseApp.auth().signOut()}>Logout</button>
</div>
<div>
<Fab color="primary" aria-label="add" size = 'large' onClick = {() => openModal()}>
<Add/>
</Fab>
{show ? <Modal/> : <div></div>}
</div>
<div>
<Router>
<div className='pub-container'>
<Link to='/publicTasks'>Public Tasks </Link>
</div>
<div className='ongo-container'>
<Link to='/onGoingTasks'>On Going Tasks </Link>
</div>
<div className='finish-container'>
<Link to='/finishedTasks'>Finished Tasks </Link>
</div>
<Route path='/publicTasks' component = {PublicTask}/>
<Route path='/onGoingTasks' component = {OngoingTask}/>
<Route path='/finishedTasks' component = {FinishedTask}/>
</Router>
</div>
</div>
);
}
export default Home;
You can share data between react components like this:
const [value, setValue] = useState("test"); // data that you want to share
return (
<Parent data={value}> // pass data to parent in your child component
);
<h1>{this.props.data}</h1> // do something with the data in the parent component

related to React js (props) css inline style

I want to more than one cards in different background color what i do ?
eg:
import React from "react";
import reactDom from "react-dom";
const BgColor=(props)=>{
return(
<>
<div className="main_div">
<div className="cards" >
<div className="card-side front" >
<div><span>C</span>opy<span>C</span>ode</div>
</div>
<div className="card-side back">
<div><i className="fas fa-copy fs-3" /><br />{props.code}</div>
</div>
</div>
</div>
</>
)
}
export default BgColor;
by pass value in app.js
and so on.....
please help me how to pass value inside the app.js
with this example is hard to to help you. Indeed, we don't know what your props object contains.
Let's assume your props contains
{
name: "toto",
code: "myCode"
}
In order to change background color based on props, you have multiples choices.
You can use dynamics classNames based on your props:
const BgColor=(props)=>{
return(
<>
<div className="main_div">
<div className="cards" >
<div className={`${props.name} card-side front`} >
<div><span>C</span>opy<span>C</span>ode</div>
</div>
<div className="card-side back">
<div><i className="fas fa-copy fs-3" /><br />{props.code}</div>
</div>
</div>
</div>
</>
)
}
See the <div className={${props.name} card-side front} > line. Go to css or scss file for this component and add a class selector inside of it.
In our example, it will be
.toto {
background: red
}
The second option is to inject directly the css inside your div.
Let's assume you send the desired background color inside your propos:
{
backgroundColor: "red",
code: "myCode"
}
In order to that, you have to do this
const BgColor=(props)=>{
return(
<>
<div className="main_div">
<div className="cards" >
<div className="card-side front" style={{backgroundColor: props.backgroundColor}}>
<div><span>C</span>opy<span>C</span>ode</div>
</div>
<div className="card-side back">
<div><i className="fas fa-copy fs-3" /><br />{props.code}</div>
</div>
</div>
</div>
</>
)
}
If you want to know more about css in React, you can check:
https://reactjs.org/docs/faq-styling.html, React.js inline style best practices, https://create-react-app.dev/docs/adding-a-stylesheet/
UPDATE
You can send an array of colors like <BgColor colors={["red", "blue"]} /> then in your BgColor component, you can map on your props like:
const BgColor=({colors})=>{
return (
<div className="main_div">
<div className="cards">
{colors.map((color, index) => {
return (
<div
className="card-side front"
style={{ backgroundColor: color }}
key={index}
>
<div>
<span>C</span>opy<span>C</span>ode
</div>
</div>
);
})}
</div>
</div>
);
}

How to add a link to images based on some condition using typescript and react?

i want to add a link to the image based on some condition using javascript and react.
what i am trying to do?
i have mobile and desktop images.
under mobile image i have text saying switch to mobile and
is clickable if the users current url is not matching mobile_url.
if the users current url matches the mobile_url then the text would be "current version" and is not clickable.
under desktop image i have text saying switch to desktop and
is clickable if the users current url is not matching desktop_url
if the users current url matches the desktop_url then the text would be "current version" and is not clickable.
below is my code that works,
function Parent () {
const currentUrl = window.location.origin + '/';
return (
<div className="Wrapper">
<Dialog>
<span>Select Version</span>
<div className="container">
<div className="block">
<span>Mobile</span>
<div className="image_wrapper"> // want to add a link here too
<img src={mobile} width={50} />
</div>
<span>
{current_url === mobile_url ? (
'Current version'
) : (
<a href={mobile_url}>Switch to mobile</a>
)}
</span>
</div>
<div className="block">
<span>Desktop</span>
<div className="image_wrapper"> //want to add a link here too
<img src={desktop} width={50} />
</div>
<span>
{current_url === desktop_url ? (
'Current version'
) : (
<a href={desktop_url}>Switch to desktop</a>
)}
</span>
</div>
</div>
</div>
);
}
Now what i want to do is as the texts switch to mobile and switch to desktops are clickable and have a link to an url. similarly i want to have links to the images mobile and desktop and should be clickable based on same conditions like texts have.
so for mobile image if current url is same as mobile_url then image is not clickable. if current url doesnt match with mobile_url then image is clickable and redirects to mobile_url
and for desktop image if current_url is same as desktop_url then image is not clickable. if current url doesnt match with desktop_url then image is clickable and redirects to desktop_url
how can i do it. could someone help me with this. thanks.
EDIT:
i have tried like below and the images are not seen.
import desktop from '../image/desktop.svg';
import mobile from '../image/mobile.svg';
interface Props {
src: any; //what should be the type here
width: any; //what should be the type here
}
function RenderImage({src, width}: Props) {
return (
<div className="image_wrapper">
<img src={src} width={width}/>
</div>
);
}
function Parent () {
const currentUrl = window.location.origin + '/';
return (
<div className="Wrapper">
<Dialog>
<span>Select Version</span>
<div className="container">
<div className="block">
<span>Mobile</span>
{current_url === mobile_url ? (
<a href={mobile_url}>
<Image src={mobile} width={50}/>
</a> ): (
<Image src={mobile} width={50} />
)
}
<span>
{current_url === mobile_url ? (
'Current version'
) : (
<a href={mobile_url}>Switch to mobile</a>
)}
</span>
</div>
<div className="block">
<span>Desktop</span>
{current_url === desktop_url ? (
<a href={desktop_url}>
<Image src={desktop} width={width}/>
</a> ) : (
<Image src={desktop} width={width} />
}
<span>
{current_url === desktop_url ? (
'Current version'
) : (
<a href={desktop_url}>Switch to desktop</a>
)}
</span>
</div>
</div>
</div>
);
}
this works fine but what should be the types for src and width in this case thanks.
I would decide what component renders before your return.
export default function Parent() {
const pathname = window.location.pathname;
const customElement = pathname === 'your mobile url'? // Check if matches
<a href={mobile_url}>Switch to mobile</a> : // if so return this one
<a href={desktop_url}>Switch to desktop</a> //else this
return (
<div className="Wrapper">
<Dialog>
<span>Select Version</span>
<div className="container">
<div className="block">
<span>Mobile</span>
<div className="image_wrapper">
<img src={mobile} width={50} />
</div>
<span>{customElement}</span>
</div>
</div>
</Dialog>
</div>
);
}
You can do the same with the images if you want a different one to display based upon current path.

How to build Tabs component Reactjs

I'm trying to build a Tabs component with ReactJS and I'm following a CSS stylesheet.So, I would love to have this as render :
<div data-container="" class="tabs tabs-horizontal">
<div class="tabs-header">
<div class="tabs-header-tab ph active" data-tab="0" style="transform: translateX(0px) translateZ(0px);">Personal
</div>
<div class="tabs-header-tab ph undefined" data-tab="0" style="transform: translateX(0px) translateZ(0px);">Job
</div>
<div class="tabs-header-tab ph undefined" data-tab="0" style="transform: translateX(0px) translateZ(0px);">
Salary</div>
</div>
<div data-container="" class="tabs-content">
<div data-container="" class="tabs-content-tab open" data-tab="0">
<div>I am a HR Specialist.</div>
</div>
<div data-container="" class="tabs-content-tab undefined" data-tab="0">
<div>No records have been added yet</div>
</div>
<div data-container="" class="tabs-content-tab undefined" data-tab="0">
<div>This type of information needs to be added by your manager</div>
</div>
</div>
</div>
And this is what the components looks like now :
<Tabs>
<TabHeaders>
<TabHeadersItem text="Personal" state="active" />
<TabHeadersItem text="Job" />
<TabHeadersItem text="Salary" />
</TabHeaders>
<TabContents>
<TabContentsItem
content="I am a HR Specialist."
open="open"
/>
<TabContentsItem content="No records have been added yet" />
<TabContentsItem content="This type of information needs to be added by your manager" />
</TabContents>
</Tabs>
So, I'm trying to find a solution, when user clicks on a header it becomes "active" and its content "open" while the others should be closed and not active.
Ok so since you've edited your question, I'll do with mine. The idea is the same: To keep the state of which tab is open, and since you don't want to keep your tabs in a list, then you need to link a TabHeader to a TabContent:
const TabHeaderItem = props => {
return (
<div
onClick={() => props.changeTab(props.text.toLowerCase())}
className={props.state ? "active" : ""}
>
{props.text}
</div>
);
};
const TabContentsItem = props => {
return <div className={props.open ? "open" : "closed"}>{props.content}</div>;
};
const TabComponent = () {
const [active, setActive] = useState("personal");
const changeTab = tab => {
console.log("tab", tab);
setActive(tab);
};
return (
<div className="App">
<div className="tabs">
<TabHeaderItem
changeTab={changeTab}
text="Personal"
state={active === "personal"}
/>
<TabHeaderItem
changeTab={changeTab}
text="Job"
state={active === "job"}
/>
<TabHeaderItem
changeTab={changeTab}
text="Salary"
state={active === "salary"}
/>
</div>
<div className="tabs-content">
<TabContentsItem
content="I am a HR Specialist."
open={active === "personal"}
/>
<TabContentsItem
content="No records have been added yet"
open={active === "job"}
/>
<TabContentsItem
content="This type of information needs to be added by your manager"
open={active === "salary"}
/>
</div>
</div>
);
}
You can check out the working example here: https://codesandbox.io/s/exciting-gauss-lbghq

making reusable component in reactjs

I have the following code, want to remove the repeated content code inside <ReactCSSTransitionGroup to a separate file - does not look straight forward to pass props to and fro from child/parent, how do I do it? is it do-able?
<div className="container">
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
<span key={this.state.showChild1} className="plus_icon">
<a onClick={() => this.onClick('child1')}>
<Img className={this.state.showChild1 ? 'plus_icon' : 'minus_icon'} />
</a>
</span>
</ReactCSSTransitionGroup>
{this.state.child1 ? <Child1-New /> : <div onClick={() => this.onClick('child1')}><Child1 /></div>}
</div>
<div className="container">
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300}>
<span key={this.state.showChild2} className="plus_arrow">
<a onClick={() => this.onClick('child2')}>
<img className={this.state.child2 ? 'plus_icon' : 'minus_icon'} />
</a>
</span>
</ReactCSSTransitionGroup>
{this.state.child2 ? <Child2-New /> : <div onClick={() => this.onClick('child2')}><Child2 /></div>}
</div>
onClick(name) {
if (name === 'child1') {
this.setState({
showChild1: !this.state.showChild1,
});
} else if (name === 'child2') {
this.setState({
showChild2: !this.state.showChild2,
});
}
planning to achieve something like:
<div className="container">
<ToggleView />
{this.state.child2 ? <Child2-New /> : <div onClick={() => this.onClick('child2')}><Child2 /></div>}
</div>
If you're using Node.js it's quite simple to manage your components in separate JS files.
Create a new JS file - ToggleView.js - as an example.
var React = require('react');
module.exports = React.createClass({
render: function() {
return (
<div>
... Your markup etc here
</div>
);
});
And then you can require it from within the JS where you want to use it:
var ToggleView = require('ToggleView.js');
And then use it:
<div className="container">
<ToggleView />
</div>
Secondly, if your state is managed at the parent which you need your children to have access to, you can simply prop down to them.
function thisFunc(val) {
// do something
};
Prop the function to the child
<ToggleView handleFunc={this.thisFunc} />
And in ToggleView.js, if you needed your to trigger on click:
...
<a onClick={this.prop.handleFunc}>
<img ... />
</a>
...
In this scenario, we prop thisFunc down to the child which will allow you to set the logic at the parent, whether you need to set state or whatever.
Hopefully this helps!

Resources