How to override className on extended component? - javascript

I am trying to position this component differently on a certain page. But when I provide it with another className property it is only using the original class's styling that was provided when declaring the component.
Component:
import React, { Component } from 'react';
import styles from './label.css';
class Label extends Component {
render() {
return (
<div className={styles.labelClass} />
);
}
}
export default Label;
Page where I want to position it differently:
import React, { Component } from 'react';
import styles from './page.css';
import Label from '../common/label.jsx';
class Page extends Component {
render() {
return (
<div>
<Label className={styles.positionLeft} />
</div>
);
}
}
export default Page;
Normally I would do this with custom styling but I have to use media
queries so this isn't possible in this situation.

Since <Label> is a custom component, you can to manually pass the className prop down.
This is a good use case for default props!
class Label extends Component {
render() {
return (
<div className={this.props.className} />
);
}
}
Label.defaultProps = {
className: styles.labelClass
}
That way, if no className is provided to Label, it will use the labelClass style, otherwise, it will use the prop.

I fixed it by adding another optional property customClass to the component.
Label
import React, { Component } from 'react';
import styles from './label.css';
class Label extends Component {
render() {
return (
<div className={styles.labelClass + ' ' + this.props.customClass} />
);
}
}
export default Label;
Page
import React, { Component } from 'react';
import styles from './page.css';
import Label from '../common/label.jsx';
class Page extends Component {
render() {
return (
<div>
<Label customClass={styles.positionLeft} />
</div>
);
}
}
export default Page;

You need to explicitly reference the className property from Label's props - try:
import React, { Component } from 'react';
import styles from './label.css';
class Label extends Component {
render() {
let { className } = this.props
if (!className) {
className = styles.labelClass
}
return (
<div className={className} />
);
}
}
export default Label;

Related

How to get label values dynamically and adding the numbers together from different input with reactjs

Created a Div and inside it I have label element and input element, I want to get different label values in each div. How to re-use my div component
instead of coding the same code again.
I have tried to search in Stackoverflow plus googles, Haven't received a better answer.
Here I have created div element with just label and input element and then I have rendured this component in App.js file:
How can I reuse the same code/component to create 2 more div and having different labels values in it? Ho can I add numbers together from different input ( which I am getting from different components input)
Appreciate all your help!
import React, { Component } from 'react';
import './calculator.css';
class Boxes extends Component {
state = {
inputOne: '',
inputtwo: '',
inputthree: ''
}
getInputValue = (e) => {
const value = e.target.value;
console.log('value: ', value);
this.setState({
inputOne: Number(e.target.value)
});
}
render() {
const { value } = this.props // destructuring
const {inputOne, inputtwo, inputthree } = this.state
return (
<div className="boxes">
<label className="boxeslevel" htmlFor="text">
{value}
</label>
<input
name="text"
type="text"
onChange={this.getInputValue}
/>
</div>
);
}
}
export default Boxes;
import React, { Component } from 'react';
import './App.css';
import Boxes from './components/calculator';
class App extends Component {
render(){
return (
<div className="wrapper">
<Boxes value= {"Value 1:"} onChange={this.props.onChange}/>
<Boxes value= {"Value 2:"} onChange={this.props.onChange}/>
<Boxes value= {"Value 3:"} onChange={this.props.onChange}/>
<ShowResult />
</div>
);
}
}
export default App;
You should pass a prop to your componente to be reuse. As you notice you are using local component state in your component, like const {value} = this.state try the same approach but with props like const {value} = this.props and then passing that prop in the component usage like
<Boxes value={“label 1”}/>
<Boxes value={“label 2”}/>
That would work. Hope it help you
Remember you can use as many props you need and access them as the same way mention above
You can do something like this:
class Boxes extends Component {
render() {
const { value } = this.props // value coming from props
return (
<div className="wrapper">
<div className="firstBox">
<label htmlFor="text">
{value}
</label>
<input name="text" type="text" />
</div>
</div >
);
}
}
export default Boxes;
and in your app component something like this:
import React, { Component } from 'react';
import './App.css';
import Boxes from './components/calculator';
class App extends Component {
render(){
return (
<div className="App">
<Boxes value={1}/>
<Boxes value={2}/>
<Boxes value={3}/>
</div>
);
}
}
export default App;
Here is live demo link
You have to use props instead of state in your Boxes component. Then you can pass the required props from the App component.
App.js
import React, { Component } from 'react';
import './App.css';
import Boxes from './components/calculator';
class App extends Component {
render(){
return (
<div className="App">
<Boxes value={"Value 1"}/>
<Boxes value={"Value 2"}/>
<Boxes value={"Value 3"}/>
</div>
);
}
}
export default App;
Boxes.js
import React, { Component } from 'react';
import './calculator.css';
class Boxes extends Component {
render() {
const { value } = this.props // destructuring
return (
<div className="wrapper">
<div className="firstBox">
<label htmlFor="text">
{value}
</label>
<input name="text" type="text" />
</div>
</div >
);
}
}
export default Boxes;

Dynamically add a span tag to the first word of a string

i'm working on a react project where i'm passing titles contained in states to a children element (see bottom).
How can i dynamically add to the first word (and only the first word cause my titles can contain 2 or 3 words) inside the this.state.title inside the child element?
//Parent
import React, { Component } from 'react';
import Child from './child';
class Parent extends Component {
state = {
title:'Admin Picture'
}
render() {
return (
<React.Fragment>
<Child title={this.state.title}>
</React.Fragment>
);
}
}
export default Parent;
//Child
import React, { Component } from 'react';
class Child extends Component {
render(){
return (
<div>
<span className="title">{this.props.title}</span>
</div>
);
}
};
export default Child;
You can do this in the Child component.
//Child
import React, { Component } from 'react';
class Child extends Component {
render() {
const splitTitle = this.props.title.split(' ');
const firstWord = splitTitle.shift();
const remainingTitle = splitTitle.join(' ');
return (
<div>
<span className="title">{firstWord}</span>
{remainingTitle}
</div>
);
}
};
export default Child;
Alternatively, you could also pass firstWord and remainingTitle to Child component as a prop. You would probably want to name them something different.

React-Chat-Widget props not forwarded

I am using the react-chat-widget and trying to call a function in the base class of my application from a custom component rendered by the renderCustomComponent function of the widget.
Here is the code for the base class:
import React, { Component } from 'react';
import { Widget, handleNewUserMessage, addResponseMessage, addUserMessage, renderCustomComponent } from 'react-chat-widget';
import 'react-chat-widget/lib/styles.css';
import Reply from './Reply.js';
class App extends Component {
handleNewUserMessage = (newMessage) => {
renderCustomComponent(Reply, this.correct);
}
correct = () => {
console.log("success");
}
render() {
return (
<div className="App">
<Background />
<Widget
handleNewUserMessage={this.handleNewUserMessage}
/>
</div>
);
}
}
export default App;
And here is the code for the custom component Reply:
import React, { Component } from 'react';
import { Widget, addResponseMessage, renderCustomComponent, addUserMessage } from 'react-chat-widget';
class Reply extends Component {
constructor(props) {
super(props);
}
sendQuickReply = (reply) => {
console.log(this.props); //returns empty object
//this.props.correct(); <-- should be called
};
render() {
return (
<div className="message">
<div key="x" className={"response"}onClick={this.sendQuickReply.bind(this, "xx")}>xx</div>
</div>)
}
}
export default Reply;
According to ReactJS call parent method this should work. However, when I print the this.props object it is empty, although the documentation of the renderCustomComponent method states that the second argument of the component to render are the props that the component needs (in this case the parent class function).
Where have I gone wrong?
The second parameter is considered as props, but it is expected to be an object. you would pass it like
handleNewUserMessage = (newMessage) => {
renderCustomComponent(Reply, {correct: this.correct});
}

How to toggle elements with a button press in React?

I have searched for 3 freaking days to find out how to toggle my mobile nav button to toggle my mobile menu. I am new to React and could do this easily with jQuery but I don't want to use jQuery. I have line for line copied an example that I found on how to show or hide an element. I can not get it to work. Any help would be much appreciated. I am using styled-components with React.
Button sub-component:
import React, { Component } from 'react';
class MenuButton extends Component {
render() {
return (
<Button onClick={this.props.toggleMenu}>
<Menu></Menu>
</Button>
)
}
}
export default MenuButton;
Menu sub-component:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class Menu extends Component {
render() {
return (
<OffCanvasMenu>
<Title>Menu</Title>
<Nav>
<NavLinks><Link to='/'>Home</Link></NavLinks>
<NavLinks><Link to='/about'>About</Link></NavLinks>
<NavLinks><Link to='/interactive'>Interactive</Link></NavLinks>
<NavLinks><Link to='/ideas'>Ideas</Link></NavLinks>
<NavLinks><Link to='/contact'>Contact</Link></NavLinks>
</Nav>
</OffCanvasMenu>
)
}
}
export default Menu;
Menu Container component with all the state:
import React, { Component } from 'react';
import Menu from './Menu';
import MenuButton from './MenuButton';
class MenuContainer extends Component {
constructor(props) {
super(props);
this.state = {
active: false
}
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu() {
const { active } = this.state;
this.setState({
//toggle value of `active`
active: !active
});
}
render() {
return (
<div>
<MenuButton onClick={this.toggleMenu}/>
{this.state.active && <Menu/>}
</div>
)
}
}
export default MenuContainer;
I can see a checkbox in ReactDev tools that shows MenuContainer has state but when the button is clicked it does not toggle the state.
onClick is handled by MenuButton component which in turns invokes toggleMenu function passed as a property. I would pass toggleMenu as property of MenuButton:
<MenuButton toggleMenu={this.toggleMenu} />

How to modify child Component content?

I have a Component like this:
<MyTimer props={+new Date()}>
<span className="year" formatter="yyyy" />
<span className="mon" formatter="mm" />
<span className="day" formatter="dd" />
</MyTimer>
MyTimer is Component like this(I just ignore some other code):
render() {
/**
* this code may not work, I just do what I think.
*/
return (<div>
{ this.props.children.map((child, i) =>
// child.children=[util.date(child.formatter)])
// set child.props.children as "util.date(child.formatter)"
}
</div>)
}
I want to change the content of span in component, which should result like this:
<span class="year">2016</span>
<span class="mon">07</span>
<span class="day">06</span>
So why do I need this, because I can change the child element type as I like:
<MyTimer props={+new Date()}>
<div className="year" formatter="yyyy" />
<span className="mon" formatter="mm" />
<p className="day" formatter="dd" />
</MyTimer>
I just do not care about what the child element is, and also className.
React has a feature called "contexts", which allow a parent component to implicitly pass some data to children.
The actual formatting then can happen in a special "formatter" component. Resulting in something like this:
import React, { Component, PropTypes } from 'react';
import moment from 'moment';
class MyTimer extends Component {
static childContextTypes = {
date: PropTypes.object
};
// expose some props to children
getChildContext() {
return {
date: this.props.date
};
}
render() {
return <div>{this.props.children}</div>;
}
}
class TimerPart extends Component {
// this is REQUIRED to receive the date from the parent
static contextTypes = {
date: PropTypes.object
};
render() {
// use it like `this.context.date`
return <span>{moment(this.context.date).format(this.props.format)}</span>;
}
}
export default class App extends Component {
render() {
return (
<MyTimer date={new Date()}>
<TimerPart format="YYYY"/>
<TimerPart format="MM"/>
<TimerPart format="DD"/>
</MyTimer>
)
}
}

Categories

Resources