rendering has not updated after componentdidmount,advice? - javascript

I'm building an application to save locations i.e countries cities regions etc. When clicking on my on click function the states of two div tags change changing the class name and making one invisible and one visible. advice?
import React, { useState }from "react";
import Area from "../ReadFolder/geographicMainComponents/areaMainComponent.jsx";
import City from "../ReadFolder/geographicMainComponents/cityMainComponent.jsx";
import Country from "../ReadFolder/geographicMainComponents/countryMainComponent.jsx";
import Neighborhood from "../ReadFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import Region from "../ReadFolder/geographicMainComponents/regionMainComponent.jsx";
import { default as AreaW} from "../WriteFolder/geographicMainComponents/areaMainComponent.jsx";
import { default as CityW} from "../WriteFolder/geographicMainComponents/cityMainComponent.jsx";
import { default as CountryW} from "../WriteFolder/geographicMainComponents/countryMainComponent.jsx";
import { default as NeighborhoodW} from "../WriteFolder/geographicMainComponents/neighborhoodMainComponent.jsx";
import { default as RegionW} from "../WriteFolder/geographicMainComponents/regionMainComponent.jsx";
export default function MenuWrapper({type,id,isEdit}){
let [edit,setEdit] = useState(isEdit);
let changer=()=>{console.log('you clicked me!');setEdit(!setEdit)}
if(type==='country'){
return(
<div key={"frommenulist"+id}>
<div className={edit ? 'd-block' :'d-none'}><CountryW id={id}/><button onClick={changer}>read</button></div>
<div className={edit ? 'd-none' : 'd-block'}><Country id={id} /><button onClick={changer}>edit</button></div>
</div>
);
}
}

It's difficult to work out what clicking those buttons is meant to do. It looks like you need only one div/button block, and clicking the edit button determines what happens (ie to make the country editable somehow).
At the moment it looks like you want to set the display to either block/none but you can't set an element's display to none and still expect to be able to click the button to reset the display because there will be no button to click on. Further: unless the type is "country" the component doesn't return anything so you need a condition in there to return something if type isn't "country" (or add a condition in the parent component to prevent the component rendering at all if that condition is met).
Here's a small example that uses local state to manage whether the div is a plain one or an editable one. Click the edit button, and then click in the div to be able to edit it. You can then click the read button to switch off contentEditable and keep the content.
const { useState } = React;
function MenuWrapper({ type, id }) {
const [ edit, setEdit ] = useState(false);
function handleClick() {
setEdit(!edit);
}
// Return a default div if type is not "country"
if (type !== 'country') return <div>Not country</div>
const divStyle = [
'country',
edit && 'edit'
].join(' ');
return (
<div>
<div>
<div
className={divStyle}
contentEditable={edit}
>Country Id: {id}
</div>
<button onClick={handleClick}>
{edit ? 'Read' : 'Edit'}
</button>
</div>
</div>
);
}
ReactDOM.render(
<MenuWrapper type="country" id="1" />,
document.getElementById('react')
);
.country { padding: 0.25em; }
.edit { border: 1px solid green; }
button { margin-top: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Related

CKEDITOR Can't see content area with DecoupledEditor

I'm using CKEDITOR5 with React and I have succeed to implement CKEDITOR in my project but when I go on my view I can only see the toolbar.
The content area is invisible until I click on it and the blue border appear.
If I remove my focus on it there is no border anymore.
Here is my code
import React, { Component } from 'react'
import CKEditor from '#ckeditor/ckeditor5-react';
import DecoupledEditor from '#ckeditor/ckeditor5-build-decoupled-document';
export default class BlogNew extends Component {
render() {
return (
<div>
<CKEditor
editor={ DecoupledEditor }
onInit={ editor => {
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
} }
onChange={(event, editor) => {
const data = editor.getData();
this.setState({ text: data })
}}
/>
</div>
)}
DecoupledEditor is dedicated to integrations which require a customized UI.
Make sure to add the style to your component:
:root {
.ck.ck-editor__editable_inline {
border: 1px solid var(--ck-color-base-border);
}
}
see # ckeditor5-ui

How to populate div with data from mobx store?

I have a div with a className of results and I want to make so that when I click on the Check button the div gets populated with the info from my store: Shop1, Shop2. I added an observable field on my CardCheck component that you toggle with the onClick event handler, and when the field is true it should display all entries in the auto array.
Here is my Component:
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import PropTypes from 'prop-types';
import './cardCheck.css';
#inject('auto')
#observer
class CardCheck extends Component {
onClick = event => {
event.preventDefault();
this.checked = !this.checked;
};
render() {
const { auto } = this.props;
return (
<div>
<div className="newsletter-container">
<h1>Enter the ID of your card:</h1>
<div className="center">
<input type="number" />
<input type="submit" value="Check" onClick={this.onClick} />
</div>
<div className="results">{this.checked && auto.auto.map(a => <div key={a.name} />)}</div>
</div>
<h1>Offers:</h1>
</div>
);
}
}
CardCheck.propTypes = {
auto: PropTypes.shape({
carCount: PropTypes.string
})
};
export default CardCheck;
and here is my store:
import { observable, action, computed } from 'mobx';
class Auto {
#observable
auto = [
{
name: 'Shop1'
},
{
name: 'Shop2'
}
];
#observable checked = false;
#action showInfo
}
}
export { Auto };
Right now nothing happens when I click on the Check button, why, and how can I make it finally work?
I tried iterating through the object with a loadash method but it did not populated the div, and I also tried this in the div results:
{this.checked &&
auto.auto.map((a, index) => <div key={index}>{a.name}</div>)}
but it didn't work and it gave me this error: Do not use Array index in keys react/no-array-index-key
I think you have mistyped with checked field. It should be this.auto.checked

Put a Font Awesome icon dynamically on input text background using React and react-fa

I'm using ReactJs and react-fa to access Font Awesome icons. I need to put one of the icons inside a text input dynamically.
Here is my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Icon } from 'react-fa';
import '../index.css';
class SearchInput extends Component {
static propTypes = {
onKeyUp: PropTypes.object,
placeholder: PropTypes.placeholder,
iconName: PropTypes.string
};
handleKeyUp = (content) => {
console.log(content);
}
render() {
let icon = <Icon name={this.props.iconName} />;
let extra = {
backgroundImage: icon
}
return (
<input className='ux-search-input' style={extra} type='text' onKeyUp={this.handleKeyUp} placeholder={this.props.placeholder} />
);
}
};
export default SearchInput;
This does not work - no icons at all. Repair that in that case I have no URLs to match, as the icon variable will be a ReactJs component.
react-fa is a React component, and it renders as html like <i class="fa fa-name" />, so you can't use it as a style. You should use something like this:
return (
<span>
{ icon }
<input className='ux-search-input' style={extra} type='text' onKeyUp={this.handleKeyUp} placeholder={this.props.placeholder} />
</span>
);
and add some styling to match proper icon position.
Instead of using React component, try using a regular icon tag in front of the input field, and then use css to move the icon to the appropriate position.
For example:
JSX:
<i class={this.props.iconName} id="icon" />
CSS:
#icon {
// Adjust margins and position to fit the input background
margin-left: 30px;
}

Add class when button clicked in react.js

I've been working on React for a few weeks now, and while I've got most of the basic syntax down (props, states), I'm struggling to draw some connections with some concepts, most notably adding classes when a state has changed. I'm trying to build a simon says game, which contains four buttons, all built using a Button component. These are initially set to have a opacity of .3 and an active state of false. When clicked, the state "active" becomes true, but I cannot for the life of me figure out how to add a css class that can give the button a full opacity. Here is my code:
class App extends Component {
constructor(){
super();
this.state = {
active: false
}
}
handleClick(){
this.setState({active: !this.state.active})
}
renderButtons(i, f){
return <Button value={i} className="button" id={f} active= {this.state.active} onClick={() => this.handleClick()}/>
}
render() {
return (
<div className="App">
{this.renderButtons("red", "buttonRed")}
{this.renderButtons("blue", "buttonBlue")}
{this.renderButtons("green", "buttonGreen")}
{this.renderButtons("yellow", "buttonYellow")}
</div>
);
}
}
And my css:
.button{
width: 100px;
height: 45px;
opacity: .3;
margin: 0 auto;
margin-bottom: 30px;
}
#buttonRed{
background: red;
}
#buttonBlue{
background: blue;
}
#buttonGreen{
background: green;
}
#buttonYellow{
background: yellow;
}
So, at this moment, I would simply like to add a class when clicking the button while still keeping the "button" class to the component. Can anyone help?
React has a couple of ways of doing this. The first is as suggested by Tudor Ilisoi, which is simply concatenating strings.
The second way is to give className an Object instead of a string. This way is arguably simpler but requires you to add the classnames module.
You can install it with either npm install --save classnames or yarn add classnames.
You can import it with:
import classNames from 'classnames';
And then you can use it in the following way:
<button className={classNames({button: true, active: this.state.active})} />
The first pair of curly brackets just tells react that we are passing a dynamic property, and the second is just the normal JavaScript syntax for objects.
Note that the object is wrapped by the classNames() function.
If we had declared it earlier, we could just as easily do:
render(){
const classes = classNames({
button: true, // we always want this class
active: this.state.active, // only add this class if the state says so
});
return (
<button className={classes} />
);
}
change className="button" to className={'button ' + f}
The expression enclosed in curly braces is evaluated as javascript and it produces a string
Also note that when using the curly brace syntax you do not have to add double quotes "" around attribute value .
When your JSX is parsed, React will generate the proper HTML attribute, for example class="button red".
if you are looking for 2021/2022 answer:
Here is an example that uses react hooks, which add the class name app to a div element when we click on a Toggle class button.
import React, { useState } from "react";import "./styles.css";
export default function App() {
const [isActive, setActive] = useState("false");
const handleToggle = () => {
setActive(!isActive); };
return (
<div className={isActive ? "app" : null}>
<h1>Hello react</h1>
<button onClick={handleToggle}>Toggle class</button>
</div>
);
}
Have you tried, pass an optional parameter to renderButtons, check it and add to class :
...
renderButtons(i, f, c){
var cssClass = c&&c!=""? "button " + c : "button";
return <Button value={i} className={cssClass} id={f} active= {this.state.active} onClick={() => this.handleClick()}/>
}
...

Add active class to link (React JS)

Have a component that's display menus from array
import React from 'react'
import { Link, browserHistory,IndexLink } from 'react-router'
$( document ).ready(function() {
$( "ul.tabs li a" ).first().addClass("current");
$("li:not(:first-child)").click(function() {
$( "ul.tabs li a" ).first().removeClass("current");
});
});
function Tabs (props) {
const numbers = props.menuitems;
const listItems = numbers.map((number) =>
<li key={number.link} ><Link to={number.link} activeClassName="current" className="tab-link">{number.linkName}</Link></li>
);
return (
<div>
<ul className="tabs" >{listItems}</ul>
<div className="tabs-header-stripe"></div>
</div>
);
}
export default Tabs
I added "curent" class by Jquery to first element, the problem is When I go from another page, class not adding, but when I just refresh page It's add normaly.
What you say is happening because the class is added in documentReady event. When yo arrive from another page the event has already been raised but of course the following code cannot find the dom element because it is not present in the page:
$( "ul.tabs li a" ).first()
What I can suggest is to avoid using jquery (and modifying the dom from outside react) and add the class directly in the react code.
I guess you wanted to do something like this:
import React from 'react'
import { Link, browserHistory,IndexLink } from 'react-router'
function Tabs (props) {
const numbers = props.menuitems;
const listItems = numbers.map((number, index) =>
<li key={number.link} ><Link to={number.link} activeClassName="current" className={index === 0 ? "tab-link current" : "tab-link"}>{number.linkName}</Link></li>
);
return (
<div>
<ul className="tabs" >{listItems}</ul>
<div className="tabs-header-stripe"></div>
</div>
);
}
export default Tabs

Categories