Loading a name based on Value from Parent Component Dynamically - javascript

Have a Parent Component which certain props such as name, queryValue and image to my Child Component which is a Custom Dropdown where as of now i am displaying the names based on a condition check for the default display in the dropdown, but now more data will be shown along with flags. I need to show the name based on the value from the parent .
Parent.jsx
<SelectCountry
options={[
{
name: 'English (USA)',
queryValue: 'en',
flagIcon: USA,
},
{
name: 'Bahasa Indonesia',
queryValue: 'id',
flagIcon: ID,
},
]}
value={localStorage.getItem('locale')} />
SelectCountry.jsx
<div className={`${baseClassName}__selected-flag-container`}>
<img
src={require(value === "en" ? '../../assets/USA.svg' : '../../assets/indonesia.svg')}
alt='desc'
/>
{value === "en" ? options[0].name : options[1].name}
</div>
//COde for the Custom DropDown will be here
As above, HAve put the condition check and its working since there were only two languages, now when more languages are added, not sure how to pick the name and also setting the src in img tag dynamically.

You are doing all in a bit of wrong way your Parent.jsx is the container component so it should hold all your logic so why not pass the appropriate data.
<SelectCountry
options={[
{
name: 'English (USA)',
queryValue: 'en',
flagIcon: USA,
src: '../../assets/USA.svg'
},
{
name: 'Bahasa Indonesia',
queryValue: 'id',
flagIcon: ID,
src: '../../assets/indonesia.svg'
},
]}
value={localStorage.getItem('locale')}
/>
& in your presentation component SelectCountry.jsx you just present.
const { options } = require('joi');
options.map((option) => {
<div className={`${baseClassName}__selected-flag-container`}>
<img src={option.src} alt='desc' />
{option.name}
</div>;
});
I haven't tested so you might need to adjust the code. Dan has some fantastic free courses on Redux where he teaches more about container & presentation component you can check it out here https://egghead.io/instructors/dan-abramov. Hope this will help you 🙂️🙂️

Related

My state open all of my submenu but i just want one submenu open

I have a left-menu and when you click on a element, the sub-menu of the element appear.
But with my actual code, when a click on a element, all of my submenu appear.
I know my method is not right, but i don't know how to do :(
My example code :
import { useState } from 'react'
export default function Menu(){
const [visibleSubCategorie, setVisibleSubCategorie] = useState(false)
const Menu = [{
name: 'Homme', link : '/homme-fr', subCategory: false
}, {
name: 'Femme', link : '/femme-fr', subCategory: [{
name: 'haut', link : '/femme-haut-fr'
},{
name: 'bas', link : '/femme-bas-fr'
}]
},{
name: 'Enfant', link : '/enfant-fr', subCategory: [{
name: 'haut', link : '/enfant-haut-fr'
},{
name: 'bas', link : '/enfant-bas-fr'
}]
}]
console.log("Menu -> Menu", Menu)
return(
<>
{Menu.map(item=>
<div>
{item.subCategory ?
<>
<button type="button" onClick={() => setVisibleSubCategorie(!visibleSubCategorie)}>{item.name}</button>
{visibleSubCategorie && item.subCategory.map(subCategorys=>
<>
<p>{subCategorys.name}</p>
</>
)}
</>
:
<a href={item.link}>{item.name}</a>
}
</div>
)}
</>
)
}``
example : when i click at the button "Femme" to see the sub-category of femme, it's like i click too on the button "Enfant".
I can create a composant and make the usestate "const [visibleSubCategorie, setVisibleSubCategorie] = useState(false)" inside and this composant inside the map but i know another method exist.
You are using the same piece of state to control all of your subCategories. A possible solution would be to useState as an array of string values for each subcategory.
const [visibleSubCategorie, setVisibleSubCategorie] = useState([])
setVisibleSubCategorie([...visibleSubCategorie, subCategorys.name])
Then check to see if that name exists in the array to know if you should show the subcategory.
{visibleSubCategorie.includes(subCategorys.name) && item.subCategory.map(subCategorys=>
You will then have to remove that item from the array when closing.
You could solve this using a method similar to what #Kyler suggested.
I suggest using a HOC, like this:
const setOpen = (setOpen, opened) => () => setOpen(!opened);
And then in your JSX:
onClick={setOpen(setVisibleSubCategorie, visibleSubCategorie)}
Note that in order for this to work, you'd have to have state for each of your sections.

How to add or remove form keys using react-final-form

single config example shows what configuration I use for inputs.
export const age = [
{
value: '',
type: 'radio',
name: 'age',
items: [
{value: 'kid', label: 'Im less than 18',
{value: 'adult', label: 'Im 18!',
],
},
];
export const someDate = [
{
type: 'date',
value: null,
name: 'someDate',
label: 'Enter date',
format: 'dd/MM/yyyy',
minDate: new Date('2019-12-31'),
maxDate: new Date('2020-03-31'),
validators: required.required.date
}
];
RFForm is a wrapper for rect-final-form Form component and I pass all components inside as children.
<RFForm
config={[...age, ...someDate, ...somethingElse]}
submit={submit}
>
<SectionBox title="Your age">
<Box mb={5}>
<InputList inputs={age}/>
</Box>
<SectionTitle title="Date"/>
<Box maxWidth="50%">
<InputList inputs={someDate}/>
</Box>
</SectionBox>
<SectionBox title="Something else">
<Box maxWidth="50%">
<InputList inputs={somethingElse}/>
</Box>
</SectionBox>
{
conditionToHideOrShowSection && <SectionWithInputs />
}
{
buttons
}
</RFForm>
I want to add a new section that will hide or show depends on what the user picks. The section should be ONLY present when the second radio button value is selected (adult). The section will contain a component with inputs from the configuration. All the fields should be required. This should only be validated when the section is present.
First question - how should I check if the specific radio button is checked. I don't have access to useForm from here and I need to hide or show section.
Second question - how to dynamically add new inputs when other inputs are changing. Remember that I have to add it to config (RFForm props) because initial value must be updated.
Actually you have access to it, but in other way via render method link
This sample shows how to conditionally show inputs link. Be aware if input hide back the data won't gone, it's still there , so to cleanup you should use change('inputName', undefined) (at least it helps me in my case)
At last you also should checkout about subscription prop. link

react tips not appearing?

I am working on a component right now that is a mapped stack of divs. Each one should have a tooltip but for the life of me I can't get the tooltip to appear
class App extends Component {
constructor() {
super();
this.state = {
options: [
{
id: '1',
label: 'Industrial Truck and Tractor Operators',
value: '53-7051',
tooltip_text: 'Operate industrial trucks or tractors equipped to move materials around a warehouse, storage yard, factory, construction site, or similar location. Excludes “Logging Equipment Operators" (45-4022).',
},
{
id: '2',
label: 'Order Clerks',
value: '43-4151',
tooltip_text: 'Receive and process incoming orders for materials, merchandise, classified ads, or services such as repairs, installations, or rental of facilities. Generally receives orders via mail, phone, fax, or other electronic means. Duties include informing customers of receipt, prices, shipping dates, and delays; preparing contracts; and handling complaints. Excludes "Dispatchers, Except Police, Fire, and Ambulance" (43-5032) who both dispatch and take orders for services.',
},
],
value: null,
className: '',
selectedClassName: '',
loading_State: true, loads
childrenCount: 0
};
this.setProps = this.setProps.bind(this);
}
setProps(newProps) { //this is going to update the state
this.setState(newProps);
}
render() {
return (
<div>
<DashControlledContainer
setProps={this.setProps}
options = {this.state.options}
value = {this.state.value}
styles = {this.state.styles}
className = {this.state.className}
selectedClassName = {this.state.selectedClassName}
loading_State = {this.state.loading_State}
childrenCount = {this.state.childrenCount}
/>
</div>
)
}
}
export default App;
//the component being returned with the tooltip
render(){
return (
<div style={this.props.styles}>
{this.props.options.map(option => (
<div key = {option} id={option.id} style={option.style}
onClick = {e=>{ //updates the props with the clicked targets value if setProps is accessible
if(this.props.setProps){
this.props.setProps({value: e.target.value})
}else{
this.setState({value:e.target.value})
}
}}
>
<span id={option.id}> {option.label} </span>
<UncontrolledTooltip placement="right" target={option}>
{option.tooltip_text}
</UncontrolledTooltip>
</div>
))}
</div>
);
}
I'm not sure where to set my target for the tooltip maybe thats the issue? I haven't been able to find many resources online. Any help would be appreciated.
I think you should provide id as a target to your UncontrolledTooltip,
<UncontrolledTooltip placement="right" target={option.id}> //set id of span as a target here
hello
</UncontrolledTooltip>
I was able to figure it out, including a string in my id fixed it for some reason?
i made my div contain id={"option"+option.id}
then I referenced it like so:
<UncontrolledTooltip placement="right" target={"option"+option.id}>
{option.tooltip_text}
</UncontrolledTooltip>

Dynamic layout of React component from JSON

I am writing a react application that is a thin client UI for a financial trading application. A core requirement is that the application be completely dynamic and configurable, including forms. Specifically, I have trade entry forms that need to be defined on the server side and stored in the database to be rendered dynamically on the client but the layout is important and needs to be able to support multiple different formats. I have seen a few libraries that take JSON form schemas and create static forms from them but none of them seem to support the kind of layout flexibility I need. For example, I need to support tabs, columns, and rows of components. My question is - can anyone suggest a ReactJs library that can do what I'm looking for? If not, how might I go about implementing it myself?
Here's a more concrete example; Suppose I have a schema fetched from the server via a REST call that looks something like this:
{
title: "Securities Finance Trade Entry",
children: [
{
containerType: "tabs",
children: [
{
title: "Common",
children: [
{
containerType: "row",
children: [
{
input: "ComboBox",
label: "Trade Type",
options: ["Repo", "Buy/Sell", "FeeBased"]
},
{
input: "ComboBox",
label: "Direction",
options: ["Loan", "Borrow"]
}
]
},
{
containerType: "row",
children: [
{
containerType: "column",
children: [
{
containerType: "row",
children: [
{
input: "text",
label: "Book"
},
{
input: "text",
label: "Counterparty"
}
]
},
{
containerType: "row",
children: [
{
input: "date",
label: "StartDate"
},
{
input: "date",
label: "EndDate"
}
]
},
{
containerType: "row",
children: [
{
input: "text",
label: "Security"
},
{
input: "numeric",
label: "Quantity"
}
]
}
]
}
]
}
]
}
]
}
]
}
Which I expect to render something like:
Basically in that schema only one tab would be shown, but there could be multiple tabs, each containing multiple children in rows and columns and potentially nested containers of tabs too. If I were to render this myself in react I would think about using .map to iterate through the json and a number of if statements to insert tags where appropriate. However, items need to be nested so I don't know how to render it such that the tag chosen is dynamic and it can have children... For example I could write:
{ if (container.containerType === "column") { () } but then I'd somehow need to embed the rest of the controls inside that tag, I don't think I could just emit a () at the end...
Another option I've considered is translating the above json to JSX on the server side and sending that. It would be fairly easy to write a parser on the Java server side that converts the above json to a JSX document and return that to the client, but then how would I render it? Is there any way I could do something like:
onComponentMount() {
fetch(webserviceUrl + 'getJsxForForm/' + props.formName)
.then(result => {this.setState({form : result});
}
render() {
return ({this.state.form});
}
But again, I don't think this will work. If I fetch the document from the server it would render it just as plain text and not actually convert it to valid html, right?
So, what are my options? I'm looking for suggestions of an existing library that would do this, or suggestions on either of the other two approaches that I'm mentioned (would they work?, how could I do it?), or alternative ideas.
Thanks,
Troy
I love the concept of dynamically rendering pages from some sort of JSON configuration.
The key will be defining Components to match containerTypes and inputs and then traversing your JSON configuration through a recursive function. In your JSON configuration, I suggest using component naming conventions wherever you want a component to be rendered. Hence, capitalizing Tabs, Row, Column, etc
Here is one example of that function. Note, in each of the containerType Components there is a call to this function with children being passed in.
See this pen: https://codepen.io/wesleylhandy/pen/oQaExK/
Example Component:
const Container = props => {
return (
<div className="container">
<h1>{props.title}</h1>
{renderChildren(props.children)}
</div>
)
}
Example Recursive-ish rendering of children
const renderChildren = children => {
return children ? children.map((child, ind) => {
const newChildren = child.children ? [...child.children] : [];
const {containerType, title, input, label, options} = child
let key;
if (newChildren.length) {
key = `${containerType}-${ind}`;
switch (containerType) {
case "Tabs":
return <Tabs
key={key}
title={title}
children={newChildren}
/>
case "Column":
return <Column
key={key}
title={title}
children={newChildren}
/>
case "Row":
return <Row
key={key}
title={title}
children={newChildren}
/>
default:
return <Common
key={key}
title={title}
children={newChildren}
/>
}
} else {
key=`${input}-${ind}`
switch (input) {
case "ComboBox":
return <SelectGroup
key={key}
label={label}
options={options}
/>
case "Text":
case "Date":
case "Numeric":
return <InputGroup
key={key}
label={label}
type={input}
/>
}
}
}) : null
}

React-table: save accessor value in state with checkbox

I am trying to use the react-table as a checkbox table. The first column will be the checkboxes, when a checkbox gets selected i want to save the id that was defined in the accessor in the state.
I have been looking at the examples and made my way trough the official documentation, so far without much luck.
My code so far:
import React from 'react';
import ReactTable from "react-table";
import 'react-table/react-table.css'
export default class TableAccessor extends React.Component {
constructor(props){
super(props);
this.state = { personId: null }
//Data to show inside the table, when an item gets selected the ID has to be set in the state
this.data= [
{id: 1, first_name: 'Emma', last_name: 'Smith', email: 'emma#example.com'},
{id: 2, first_name: 'Liam', last_name: 'Miller', email: 'liam#example.com'}
];
//Header data for the table
this.columns = [
{Header: '#', accessor: 'id', Cell: () => <input onChange={() => {
//Here i want to get the ID of the selected item defined in this.data
this.setState({personId: this.data.id});
}} type="checkbox"></input>},
{Header: 'First name', accessor: 'first_name'},
{Header: 'Last name', accessor: 'last_name'},
{Header: 'Email', accessor: 'email'}
];
}
logger = () => {
console.log("personId: " + this.state.personId)
}
render() {
return(
<div className="wrapper">
<button onClick={this.logger}>Print</button>
<ReactTable data={this.data} columns={this.columns} />
</div>
);
}
}
I also want to be able to only check one checkbox at the time. I saw people solving this with radio buttons, however when i change the type="checkbox" to type="radio" i can still select more than one item.
Who can help me overcome this issue and explain me what the best way is to save the accessor value in the state?
Thanks in advance :)
First of all, why would you use react-table package? What is the benefit of using 3rd party package instead of writing it yourself?
Steps I'd take:
Write static HTML table with stuff you need
Map the data array to the table rows and populate it. Make sure to add data-id attribute and pass the id attribute from the array to each element
Add onClick handlers which get the data-id attribute when clicked.
You can use computed property names (example here) and generate state like this: this.setState( {[savedId]: value} )
And that should be it.

Categories

Resources