how to use props to change className ? (reactjs/css) - javascript

I don't succeed by defining a function
and call this function below by just changing className for each element ..
Here is the code:
const ProgressBar = (props)=>{
return(
<div className={props.styleName}>
<div className={classes.ProgressBarGradient}>
<div className={classes.GradientHider}/>
</div>
</div>
)
}
const GridContent = (props)=>{
return (
<div className={classes.Container}>
<h3 className={classes.Title1}>progress vs target</h3>
<h3 className={classes.Title2}>weekly goal</h3>
<h3 className={classes.Title3}>monthly goal</h3>
<ProgressBar styleName="ProgressBar1"></ProgressBar>
</div>
);
}
What I want is to change only the className of the first div when I call the function below.
Thank you so much :)
PS: I use css modules so when I call my class I usually do className={classes.className}

In your ProgressBar use this :
<div className={classes[props.styleName]}>

Related

How to render a component outside the component that contains the function that renders the first component?

The situation is a bit complicated:
inside a component called "LeftSectionHeader" I have a div, which when clicked must render a component;
the component to be rendered is called "ProfileMenu", and is basically a div that must be rendered on top of "LeftSectionHeader" itself and another div;
All these components are rendered inside another component called "Main".
The problem is that if I define the function inside "LeftSectionHeader", "ProfileMenu" will be rendered inside, while I need it to not only be rendered outside, but even cover it; that's why you'll see some boolean vars inside "Main", because that is the only way i could render it, but it still doesn't cover the other divs. I'll attach the code of each component and how the final result should look below.
LeftSctionHeader:
function LeftSectionHeader(){
return(
<div class="left-section-header">
<div class="crop" ><img src="./images/profiles/anonimous.png" /></div>
</div>
);
}
The div belonging to the "crop" class is the one that must be clicked to render "ProfileMenu"
ProfileMenu:
function ProfileMenu(){
return(
<div class="profile-side-menu">
//A lot of boring stuff
</div>
);
}
There are some functions related to this component, but they are not important, so I didn't put them, just ignore it
Main:
var p=true;
var m=true;
function Main(){
return(
<div class="main">
<Header />
<div class="left-section">
{m ? <div><LeftSectionHeader /><LangMenu /></div> : <ProfileMenu />}
</div>
{p ? <PostPage /> : <NoPostsMessage />} //Ignore this line
</div>
);
}
Before clicking on the orange div
After clicking
This might help as guidline, hopefully!
function LeftSectionHeader({ onClick }){
return(
<div class="left-section-header" onClick={onClick}>
<div class="crop" ><img src="./images/profiles/anonimous.png" /></div>
</div>
);
}
function Main(){
const [showProfile, setShowProfile] = useState(false);
return(
<div class="main">
<Header />
<div class="left-section">
{!showProfile ? (
<div>
<LeftSectionHeader onClick={() => setShowProfile(true)} />
<LangMenu />
</div>
) : <ProfileMenu />}
</div>
{p ? <PostPage /> : <NoPostsMessage />} //Ignore this line
</div>
);
}
The simplest solution might be to pass a handler into the header component to toggle the menu:
function App () {
const [showMenu, setShowMenu] = useState();
return (
<div>
<Header onMenuToggle={() => setShowMenu(!showMenu)} />
{ showMenu && <Menu /> }
</div>
)
}
function Header ({ onMenuToggle }) {
<div onClick={onMenuToggle}>...</div>
}
Caveat: This will cause the entire App component to re-render when the menu state changes. You can mitigate this by either
A) placing the menu state closer to where it's actually needed, like in the sidebar component instead of at the top, or
B) using a context or other orthogonal state store.
Another approach would be to leave the state handling in the LeftSectionHeader component and then use a React portal to render the menu elsewhere in the DOM.

React render array of objects in cells of Bootstrap grid

I have an array of components and I want to render each element in a different cell. The length of the array can be always different and can be more then 12 elements that are the limit of the cells in the Bootstrap grid system. So if the elements are more then 12 I need to create a new rows.
In my RENDER method I have this:
let components = this.state.elements.map(
(currElement, index) => this.renderElement(currElement, index)
);
return (
<div className="wrap-content container-fluid">
<section id="box-main" className="container-fluid">
<div className="row flex-items-xs-center">
<div className="col-xs">
<header>
<h4>{this._title}</h4>
</header>
</div>
</div>
{components}
</section>
</div>);
The method renderElement now render each element in a row, but I want to render in a cell but I don't know how to do. The ElementItem is a component that render the single element.
renderElement(element, index)
{
return(
<div key={index} className="row flex-items-xs-center">
<div className="col-xs">
<ElementItem element={element} propA={element.propA} template={2} />
</div>
</div>
);
}
Christian, I'm not sure if I understood your question. But if you want each element rendered in a column(cell) you must declare your components inside row and then specify the breakpoints. Something like this:
const MainComponent = props =>{
const elements = elements.map(element =>{
return(<div className="col md-4"> {element} </div>);
})
return(
<div className="row">
{elements}
</div>
)
}

React how to get item props from event.currentTarget

Does react have a clean way to get the this.props.values from a list item?
I basically want to get the current items props so I can populate a modal dialog with the data. as per below functions the custom props that I specify like 'id' are accessible, but I really would like to do something like this and have all the props
event.currentTarget.this.props.note
Handler
clicker(event){
console.log('clicking the clicker');
console.log(event.currentTarget.id);
this.setState({isEdit: true});
console.log(this.state.isEdit);
}
View
<div id={this.props.id} onClick={this.clicker} className="aui-item page-card off-track notecards">
<div className="project-details">
<div className="card-container">
<div className="left">
<h6>Title</h6>
<span>{this.props.note.content}</span>
<h6 className="compact">Last status report</h6>
<span>{this.props.note.updatedAt}</span>
</div>
<div className="right">
<span>something</span>
</div>
</div>
</div>
</div>
You can directly access props inside clicker
clicker(event){
console.log('clicking the clicker');
console.log(this.props.id);
this.setState({isEdit: true});
console.log(this.state.isEdit);
}
In this case it would be better to create separate component. In my opinion not necessary to create big huge views.
So, your component should be like this:
function Item({
id,
updatedAt,
content,
onClick,
}) {
// We should pass `id` variable to `onClick` handler.
return (
<div onClick={() => onClick(id)} className="aui-item page-card off-track notecards">
<div className="project-details">
<div className="card-container">
<div className="left">
<h6>Title</h6>
<span>{content}</span>
<h6 className="compact">Last status report</h6>
<span>{updatedAt}</span>
</div>
<div className="right">
<span>something</span>
</div>
</div>
</div>
</div>
);
}
Or, if you don't want to use separate component, you can access this.props variable from clicker event handler:
clicker(event){
// this.props are accesible here.
this.setState({isEdit: true});
}

React.js: project is not working

I am making a simple React.js project. The project can be found here.
The HTML is as follows:
<header>
<div class="container-center">
<h1 class="text-center">Markdown Previewer</h1>
</div>
</header>
<div class="container-center" id="main-container">
</div>
<footer>
<div class="container-center">
<p class="text-center">Copyright © Sergey Kosterin, 2016. All rights reserved.</p>
</div>
</footer>
The Javascript code is as follows:
var RawTextContainer = React.createClass({
render: function(){
return (
<h1>Raw Text</h1>
);
}
});
var MarkdownContainer = React.createClass({
render: function(){
return (
<h1>Markdown Text</h1>
);
}
});
var MainAppContainer = React.createClass({
render: function(){
return (
<div class="row">
<div class="col-md-6">
<RawTextContainer />
</div>
<div class="col-md-6">
<MarkdownContainer />
</div>
</div>
);
}
});
ReactDOM.render(<MainAppContainer />, document.getElementById('main-container'));
I want the app to show me two columns containing some text. But I don't see anything. What am I doing wrong?
React doesnt use class keyword. Instead of that it should be className. Here is a useful link about class & className keywords.
var MainAppContainer = React.createClass({
render: function(){
return (
<div className="row"> // className instead of class
<div className="col-md-6"> // className instead of class
<RawTextContainer />
</div>
<div className="col-md-6"> // className instead of class
<MarkdownContainer />
</div>
</div>
);
}
});
If it isn't the answer, then you have to provide a bit more information about your problem e.g. stack trace, errors etc. It's quite difficult to guess where is your problem.
Update
Worked example -> Pen Example i don't know why, but Pen doesnt recognise ReactDOM or you didn't include it. You can try to render your component through React.
React.render(<MainAppContainer/>, document...)
Also if you open browser console, you will get more information about some errors, or required statements (in your case jQuery isn't included file).
Thanks.

Why is not this onClick work?

I have the following reactJS/JSX code :
var LikeCon = React.createClass({
handleClick: function(like) {
return;
},
render(){
return this.renderLikeButton(this.props.like, this.props.likeCount)
},
renderLikeButton(like, likeCount){
return (
content = <div className={like==true ? "likeButConAct" : "likeButCon"}>
<div className="likeB" onClick={this.handleClick(!like)} > </div>
{ likeCount > 0 ? <div className="likeCount">{likeCount}</div>: null}
</div>
);
}
});
The problem is that handleClick will never be triggered even when I click the likeB div? Why?
Edit :
This is the code that uses the LikeCon component :
var TopicComments = React.createClass({
render: function() {
var comment = this.props.data.map(function(com, i) {
return (
<article>
<div className="comment">
<div className="tUImgLnk">
<a title={com.UserName} target="_blank" href={com.UserInfoUrl}>
<img className="tUImg" src={com.UserPicSrc} />
</a>
</div>
{com.UserName}
<div className="content">
{com.Message}
</div>
<div className="status">
<div className="dateCreated dimText">
{com.DateCreated}
</div>
<LikeCon like={com.Like} likeCount={com.LikeCount} />
<article></article>
</div>
</div>
</article>);
}.bind(this));
return(
<div className="comments">
{comment}
</div>
);
}
});
I suspect the problem is that the LikeCon is generating a markup for the TopicComment so the handleClick is not really there when triggered from the TopicComment. Is there a simple way to fix this?
You should be passing handle click event like so:
<div className="likeB" onClick={this.handleClick.bind(this,!like)} > </div>
With your current version you are passing result of executing this.handleClick(!like) to onClick handler which is undefined.
With above version you are passing a function which takes !like as its first parameter when executed.
Update:
Also since your div only contains a single space character, it is difficult to find the space character and click on it. If you add a text and click on that text, you will see the handle function is being executed:
working fiddle : http://jsfiddle.net/an8wvLqh/

Categories