How to add conditional statement inside react fragment - reactjs

Inside of the react fragment I have to add conditional statement. On basis of the conditional statement, return what expected
return (
<React.Fragment>
<Toolbar
pageTitle={i18next.t('TITLE')}
iconButtons={this.state.icons}
{this.props.abc && this.props.abc.operation ?(
moreButton={moreButton}
):null}
/>
if this.props.abc.operation is present then only show morebutton if not show only iconbuttons this is my condition and above is the code i tried. any help would be really appreciated.

<>
<Toolbar
pageTitle={i18next.t('TITLE')}
iconButtons={this.state.icons}
moreButton={this.props.abc && this.props.abc.operation && moreButton}
/>
</>
Try to use this.

Instead of conditional rendering you can do like below.
isAbcOperationExist = (args) => {
if(args && args.operation){
return true;
}
return false;
}
Now inside component props:
<Toolbar
pageTitle={i18next.t('TITLE')}
iconButtons={this.state.icons}
showMoreButton={() => this.isAbcOperationExist(this.props.abc)}
/>
Based on result returned boolean value by method isAbcOperationExist you can show or hide moreButton
More Example:
Assumption this is class based component:
class YourComponent extends React.Component {
constructor(props){
super(props)
}
isAbcOperationExist = (args) => {
if(args && args.operation) {
return true;
}
return false;
}
render (){
return (
<Toolbar
pageTitle={i18next.t('TITLE')}
iconButtons={this.state.icons}
moreButton={moreButton}
showMoreButton={() => this.isAbcOperationExist(this.props.abc)}
/>
)
}
}
For Toolbar Component assuming it as functional base component:
const Toolbar = ({pageTitle, iconButtons, showMoreButton, moreButton}) => {
return(
<div>
{
showMoreButton ? <button onClick={moreButton}>Show More</button> : null
}
</div>
)
}

React Fragment has nothing to do with this. You also can't manipulate component props like this. The idea would be to have a single prop for iconButtons and moreButton and and do the logic what to show inside Toolbar component

Related

How to make react child component using conditional

So usually we create child component of react using code seems like this :
const component =(<button>Bla Bla</button>)
How you can create that using conditional? I have to try this one :
const component =(()=>{
if(true){
return(<button>Bla Bla</button>)
}else{
return null
}
})
but that code throw error : Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
How to write that code properly ?
You can do that by simply passing a prop to it. Make the component like:
const Button = ({ display }) => {
return <>
{display && <button>I am Button<button>}
</>
}
Now if you want to display it you can just call it as:
<Button display={true} />
Hope this works for you.
You can do it like this
const component = true ? (<button>Bla Bla</button>): null
true can be any conditional you want to check
const myComp = ({value}) =>(
<div>
{
value &&
<myComp />
}
<div>
From my comment above. One way is to use conditional rendering in you JSX code
const bio = this.state.displayBio ? (
<div>
This is true false condition
<button onClick={this.toggleDisplay}>Show Less</button>
</div>
) : (
<div>
<button onClick={this.toggleDisplay}>Show More</button>
</div>
);

ReactJS: How to map items in conditional statements

I have a react component that allows a user to click a button in the header and add different input types.
export default class ElementContainer extends Component {
render() {
return (
<div className="append-header">
<Headline buttonCheck={this.props.buttonCheck} />
<SubHeadline buttonCheck={this.props.buttonCheck} />
<URLButton={this.props.buttonCheck} />
</div>
)
}
}
I'm trying to implement react-beautiful-dnd into the project so that those inputs can be repositioned like a list in Trello.
Looking at that library (and other similar libraries), they use the data as lists in order to perform the drag and drop function.
The items in my app are added to the view by conditional rendering:
export default class InputShow extends Component {
render() {
const { node } = this.props;
return (
<div className="editor-div" >
{
(node.type === 'buttonA') ?
<textarea
//omitted code
id={node.id}
onChange={this.props.inputContentHandler} />
:
(node.type === 'buttonB')
?
<URLButton
url={this.url}
id={node.id}
title={this.title}
/>
:
""
}
</div >
)
}
}
I've tried to map the items by creating a state for items (additions)
export default class InputShow extends Component {
constructor(props) {
super(props)
this.state = {
additions: []
}
}
render() {
const { node } = this.props;
return (
<div className="editor-div" >
{this.state.additions.map(addition => (
<div key={addition.id}>
{
(node.type === 'buttonA') ?
<textarea
//omitted code
id={node.id}
onChange={this.props.inputContentHandler} />
:
(node.type === 'buttonB')
?
<URLButton
url={this.url}
id={node.id}
title={this.title}
/>
:
""
}
</div>
))}
</div >
)
}
}
I didn't get any errors, however now when I click on the buttons, no data is being displayed in the view. I've done simple maps in the past with API and local data but I've never tried it with ternary statements. Thanks for any feedback on a solution to this problem.
What you can do is separate the view logic from the code and create a functional component. Pass the values from the main as below:
{this.state.additions.map(addition => (
return <CustomTemplate id={addition.id}
nodeId={node.id} changeEvent={this.props.inputContentHandler}
nodeType={node.Type} url={this.url} title={this.title}/>))}
Create CustomTemplate something like this
const CustomeTemplate =(props)=>(
use props to get the values in the templates
)

change the state of the child component

I am having a Parent Component and a child component
export default class CityPart extends Component {
constructor(props)
{
super(props);
this.state ={
citylist: citylist
selectedflag:1
}
}
Clickme(idd){
this.setstate({selectedflag:idd})
}
render() {
return (
<div className="CityPartMain">
{this.state.citylist.map((item)=>{
return (
<EachCity name ={item.name} key={item.id}
id={item.id}
selected={this.state.selected}
Clickme ={this.Clickme}
/>
)
})}
</div>
);
}
}
export default class EachCity extends Component {
render() {
const {name,id,selected,Clickme} = this.props;
return (
<button
onClick={this.Clickme(id)}
className={selected===parseInt(id,10)?"selectedcity": "EachCityMain"}>
<p>{name}</p>
</button>
);
}
}
whenever i click on the button i want that id should come to my parent component and it should get updated in the selectedflag of the parent state.
Thanks for help in advance.
You have made two mistakes.
First one is in your parent - this is how you should implement method Clickme:
Clickme = (id) => {
this.setState({selectedflag:idd})
}
In your implementation this means object, which is calling method (child), so this.setState() will work for child.
When you use lambda expression - it will work for parent.
Second mistake is how are you calling Clickme in your child component.
You should make it like:
<button
onClick={() => Clickme(id)}
className={selected === parseInt(id,10) ? "selectedcity" : "EachCityMain"}
>
<p>{name}</p>
</button>
If you are calling function without parameters, you can just pass function to onClick. In your case you have to create anonymous function to call it with parameter. Additionaly this is unnecessary.
Your Clickme callback is getting called right away (remember, function() is called right then) and you are just storing the result of that call in the onClick handler. You're also using this. Try instead setting it as a callback using an anonymous arrow function.
export default class EachCity extends Component {
render() {
const { name, id, selected, Clickme} = this.props;
return (
<button
onClick={() => Clickme(id)}
className={selected===parseInt(id,10) ? "selectedcity" : "EachCityMain"}
>
<p>{name}</p>
</button>
);
}
}
If this is unclear to you and how and why it works, I can add a codesandbox example with more detail.

React conditional components mount multiple times

I'm not using react router and simply have some condition to show and hide certain components.
return (<div className={classes.content}>
{ Navigation[this.state.view] && Navigation[this.state.view].selected === 'colors' && <Colors /> }
{ Navigation[this.state.view] && Navigation[this.state.view].selected === 'typography' && <Typography /> }
{ Navigation[this.state.view] && Navigation[this.state.view].selected === 'decoration' && <Decoration /> }
{ Navigation[this.state.view] && Navigation[this.state.view].selected === 'footer' && <Footer /> }
</div>)
This will call componentDidMount inside each component with the number of times that those conditions are met. Can you pinpoint what's wrong with the way I'm showing and hiding the components.
One way to solve your problem could be to store the map to your pages in your class or in any variable outside of your render. The component will need to be wrapped into functions to not be mounted when initializing your variable.
This can be done in your constructor for example :
this.pages = {
colors: () => <Colors/>,
typography: () => <Typography/>,
decoration: () => <Decoration/>,
footer: () => <Footer/>
}
Now, in your render, just take out the navigation page name you wish to load, extract the right one from your JSON object and call the function to render the correct element without loading the others :
const nav = Navigation[this.state.view]
return (
<div className={classes.content}>
{nav && this.pages[nav.selected]()}
</div>
)
I think it's because of that you are creating a react element every time those conditions are met. So I believe you can fix that by creating those components once, and returning them as needed.
So you need something like this:
class Something extends Component {
constructor() {
this.pages = {
colors: <Colors />,
typography: <Typography />
}
}
render() {
return (
<div className={classes.content}>
{ Navigation[this.state.view] && Navigation[this.state.view].selected === 'colors' && this.pages.colors }
{ Navigation[this.state.view] && Navigation[this.state.view].selected === 'typography' && this.pages.typography }
</div>
)
}
}
(You can also implement some lazy-loading behavior to createElements as needed and returning the previously created one if is available)

How to show a block of collapsible text on click of button

I am trying to implement a collapsible component. I have designed it such as, on click of a button, a block of dynamic text will appear. I made a functional component and using the tags in a class. The name of the component is, CustomAccordion.jsx and using this component in Container.jsx
I have tried to create a button and a function for onClick event.
Part of the CustonAccordion.jsx
const handleToggle = () : string =>{
let content = this.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
}else{
content.style.maxHeight = content.scrollHeight +'px';
}
}
export default function CustomAccordion(props: PropType): React.Component<*> {
const { title, children } = props
return(
<div>
<AccordionButton onClick={() => this.handleToggle()}>{title}</AccordionButton>
<AccordionContent>
<p>{children}
</p>
</AccordionContent>
</div>
)
}
Part of calling Container.jsx
<CustomAccordion title = {this.props.name}>
<p>This is the text passed to component.</p>
</CustomAccordion>
<br />
This does not show the expanded text and it seems that the click event does not work properly. I am very new in react, guessing the syntax might be incorrect.
In react you should generally try to avoid touching DOM directly unless you really have to.
Also you are accessing the handleToggle function wrongly. It should be onClick={() => handleToggle()} because this in your case is window/null and so it has no handleToggle method.
Instead you can use a stateful class component to achieve the same thing.
export default class CustomAccordion extends React.Component {
state = {show: false};
toggle = () => this.setState({show: !this.state.show});
render() {
const {title, children} = this.props;
const {show} = this.state;
return (
<div>
<AccordionButton onClick={this.toggle}>{title}</AccordionButton>
{show && (
<AccordionContent>
<p>{children}</p>
</AccordionContent>
)}
</div>
)
}
}
If you want to have some kind of animation, you can set different className based on the show state instead of adding/removing the elements.

Resources