AntD Tree: need help! can't pass react element as icon OR title for antd tree - reactjs

I'm using the AntD tree and I have a react element that I want to pass as either an icon or a title because it has custom styling. Due to it being IP I can't share too much code, but my question is:
how can I pass a react element (see below i.e. generic name) as either a title or icon and have antD tree render it?
i.e. this is what I want to pass as a prop to the icon or title
import React from 'react';
const genericName = (props) => {
// code uses props to get some infor for Color
// cant share code due to proprietary reasons
// but it is not needed for this question
const colorHTML = getColor(Color);
return (
<div>
<div className={`colors from`}>${colorHTML}</div>
{pin}
</div>
);
};
export default genericName;
in my console you can see node.icon is a typeof react.element. I want to target that and just pass the prop into antD tree as either title or icon
i.e.
return (
<Tree
icon={node.icon}
/>
)
I've searched and similar answers were given before antD forbid the use of children and strictly allows treeData. All examples I see only use strings in titles/icons, but since antD documentation is very limited, I need to know if my use case is possible. Right now, for the life of me I can't understand why it doesn't populate.
Thank you in advance.

It should definitely work to put a JSX component as title within treeData. Take a look at this snippet, I added a Icon here in one of the titles:
import React from 'react'
import { RightCircleOutlined } from '#ant-design/icons'
type Props = {}
import { Tree } from 'antd';
import type { DataNode, TreeProps } from 'antd/es/tree';
const treeData: DataNode[] = [
{
title: <span>{<RightCircleOutlined />} parent</span>, //icon added here
key: '0-0',
children: [
{
title: 'parent 1-0',
key: '0-0-0',
disabled: true,
children: [
{
title: 'leaf',
key: '0-0-0-0',
disableCheckbox: true,
},
{
title: 'leaf',
key: '0-0-0-1',
},
],
},
{
title: 'parent 1-1',
key: '0-0-1',
children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-0-1-0' }],
},
],
},
];
const Demo: React.FC = () => {
const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
};
const onCheck: TreeProps['onCheck'] = (checkedKeys, info) => {
console.log('onCheck', checkedKeys, info);
};
return (
<Tree
checkable
defaultExpandedKeys={['0-0-0', '0-0-1']}
defaultSelectedKeys={['0-0-0', '0-0-1']}
defaultCheckedKeys={['0-0-0', '0-0-1']}
onSelect={onSelect}
onCheck={onCheck}
treeData={treeData}
/>
);
};
export default Demo;

Related

Storybook saving values of properties with the same name

If I am at the docs page and then go to another component that has the same name on the properties it will cause the value of the control input of that property to the keep that same value.
What's even odder is that storybook isnt even using that value, the component is still rendered with the "real" value.
This same bug is causing some controls to just be "set object", "set string" etc.
If I go to the canvas page and back, or if click the "reset controls" button it will restore to default and show objects and strings as they should.
Anyone encountered this and figured out a solution?
I am suspecting it has something to do with using Typescript, and some of the documentations being automatically generated somehow, is it possible to turn this off?
Here is some example code of a story:
import Component from "##/components/Component";
import { Meta, Story } from "#storybook/react";
const meta: Meta = {
title: "Components/Component",
component: Component,
};
export default meta;
const Template: Story = (args) => (
<div style={{ maxWidth: "500px" }}>
<Component
header=""
items={[]}
{...args}
/>
</div>
);
export const Story = Template.bind({});
Story.args = {
header: "Header",
list: [
{
name: "Test 1",
},
{
name: "Test 2",
},
],
};
Story.argTypes = {
list: {
description: "List of items",
table: {
type: {
summary: "Array",
},
},
},
};
I figured it out.
I had several components all under the same title: "XXX/YYY" instead of "XXX/YYY/ComponentName".

Fluent-UI's dropdown and combobox both not working

I have a React app with Fluent-UI 8 set up using npm install #fluentui/react according to the documents from Microsoft.
When I try their combobox or dropdown components, the dropdown list doesn't appear when clicked on it. I use their examples from the docs, which compiles without errors. But none of their examples work out of the box, and no other information is provided.
The problem is that the dropdown list does not appear when clicked on. Not in Edge, not in Firefox. When I check the elements on the page, I do not see the html elements with the list items, although I can cycle through them with the arrow keys. The list appears from the side when the window is tablet format, and setting ResponsiveMode did nothing. Whith a normal screen however, nothing is displaying, and no onchange events are fired.
This is my code for the dropdown:
import { IStackTokens, ResponsiveMode, Stack } from '#fluentui/react';
import { Dropdown, DropdownMenuItemType, IDropdownOption, IDropdownStyles } from '#fluentui/react/lib/Dropdown';
const dropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };
const DropdownControlledMultiExampleOptions = [
{ key: 'fruitsHeader', text: 'Spooler status', itemType: DropdownMenuItemType.Header },
{ key: 'apple', text: 'Apple' },
{ key: 'banana', text: 'Banana' },
{ key: 'grape', text: 'Grape' },
{ key: 'broccoli', text: 'Broccoli' },
{ key: 'carrot', text: 'Carrot' },
{ key: 'lettuce', text: 'Lettuce' },
];
export const DropdownList: React.FunctionComponent = () => {
const stackTokens: IStackTokens = { childrenGap: 20 };
return (
<Stack tokens={stackTokens}>
<Dropdown
placeholder="Select an option"
label="Disabled responsive"
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
responsiveMode={ResponsiveMode.unknown}
/>
<Dropdown
placeholder="Select an option"
label="Responsive with panel"
options={DropdownControlledMultiExampleOptions}
styles={dropdownStyles}
/>
</Stack>
);
};
Which I load in my app.tsx
function App() {
return (
<div className="App">
<DropdownList/>
</div>
);
}
Does anyone have an idea how I can get this to work? Or what is causing this?
EDIT and possible solution: It seems that removing the <React.Strict> tags in index.tsx does the job. Don't know why, but then the Fluid-UI controls work fine.

When trying to return dynamic component, getting undefined error?

I want to switch between components depending on passed prop. If type === 'check' - render CheckList, otherwise render RadioList. Both of these components accept same props. I tried following example given [here][1]. But when I tried running the code, I got error:
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined.
You likely forgot to export your component from the file it's defined in,
or you might have mixed up default and named imports.
Check the render method of `List`.
My code in List.tsx is:
import CheckList from './Check/CheckList';
import RadioList from './Radio/RadioList';
import Props from './typings';
const list = {
check: CheckList,
radio: RadioList,
};
const List = ({type = 'radio', selected, options, callback}: Props) => {
const ListType = list[type];
return (
<ListType list={options} selected={selected} callback={callback} />
);
};
export default List;
When in return I replace ListType with either RadioList or CheckList - it works. I don't understand why it breaks when I use ListType. I checked all imports/exports and the fact that components work fine outside of List shows that they are not the problem.
I actually call for List inside RadioList component, so that it can return either radio list or check list for children:
import React from 'react';
import RadioButton from '../../../atoms/RadioButton/RadioButton';
import Props from './typings';
import {StyledSubcategory} from './styles';
import List from '../List';
const RadioList = ({list, selected, group, callback}: Props) => {
return (
<>
{list.map((option, key) => (
<>
<RadioButton
key={key}
checked={false}
label={option.label}
value={option.value}
callback={callback}
/>
{option.sublist && (
<StyledSubcategory $visible={true}>
<List
type={option.sublist.type}
selected={false}
options={option.sublist.options}
callback={callback}
/>
</StyledSubcategory>
)}
</>
))}
</>
);
};
export default RadioList;
My props for list are:
const list = {
type: 'radio',
options: [
{
label: 'all',
value: 'all',
},
{
label: 'painting',
value: 'painting',
sublist: {
type: 'radio',
options: [
{label: 'all', value: 'all'},
{label: 'acrylic', value: 'type-acrylic'},
{label: 'oil', value: 'type-oil'},
{label: 'watercolour', value: 'type-watercolour'},
],
},
},
],
};
UPDATE:
I found what the issue was. My list object with my components was declared outside of my List, however once I brought it inside it worked:
import CheckList from './Check/CheckList';
import RadioList from './Radio/RadioList';
import Props from './typings';
const List = ({type = 'radio', selected, options, callback}: Props) => {
const list = {
check: CheckList,
radio: RadioList,
};
const ListType = list[type];
return (
<ListType list={options} selected={selected} callback={callback} />
);
};
Can someone explain why it's the case?
export default List;
[1]: https://stackoverflow.com/a/40896168/3629015
The problem is with the type property of the List component. You are passing option.sublist.options value to it, which is most probably undefined, and it overrides the default value radio as well.
Please make sure the value is not undefined, or pass it like so;
<List
type={option?.sublist?.type ?? 'radio'}
selected={false}
options={option.sublist.options}
callback={callback}
/>

react typescript set default value multiselect

I am using this module
import { MultiSelect } from "react-multi-select-component"
and creating form by this
const [selected_to2, setSelected_to2] = useState([]);
<MultiSelect
options={options2}
value={selected_to}
onChange={setSelected_to}
labelledBy="Select2"
/>
then I creating multiselect component with default value using this
selected_to2.push({
value: item?.Code,
label: item?.Name
})
but returning value with 4 time called in the multiselect form, any proper way to set default value of multiselect then also add and remove in multiselect item?
React state must updated by set function. Edit the value directly will not work.
So you need do
setSelected_to2(s => [...s, {
value: item?.Code,
label: item?.Name
}])
First of all you are updating state is a wrong way
Wrong way
selected_to2.push({
value: item?.Code,
label: item?.Name
})
Right way:
setSelected_to2([{
value: item?.Code,
label: item?.Name
}
])
Here's a quick example that I did might help you, remember your default value must be an array of selected values since it's a multiselect component.
JSX
import { useState } from "react";
import { MultiSelect } from "react-multi-select-component";
import "./App.css";
const options = [
{ label: "The Godfather", value: 1 },
{ label: "Pulp Fiction", value: 2 },
];
const App = ({ editMode = true }) => {
const [value, setValue] = useState(editMode ? [options[1]] : []);
return (
<div className="App">
<MultiSelect
options={options}
value={value}
onChange={(selectedValues) => setValue(selectedValues)}
labelledBy="Select2"
/>
</div>
);
};
export default App;

Access selected value from react's Select Component

Hello dear community,
I want to create a very basic website for my school assignment.
I have a dropdown menu with a Select Component as its implementation. I need to access the selected value, which is a currency in my case, in order to update the information displayed on the page once a currency has been selected.
I am kind of frustrated since I wasn't able to find a helpfull solution to my relatively basic problem (I think it's basic :D)
My component class here:
import { Component } from "react";
import Select from 'react-select';
interface DropdownMenuProps {
values: [{}]
defaultValue: string
}
interface DropdownMenuState { }
/**
* Represents a Dropdown Menu
*/
export default class DropdownMenu extends Component<DropdownMenuProps, DropdownMenuState> {
render() {
return (
<div style={{ width: '120px' }}>
<Select id="dropdown-menu"
placeholder={this.props.defaultValue}
options={this.props.values}
// getOptionValue={(option) => option.value}
// getOptionLabel={(option) => option.label}
/>
</div>
)
}
}
This is how I create a dropdown menu compent:
<DropdownMenu defaultValue="Currency" values={[{ label: "EUR", value: "EUR" }, { label: "GBP", value: "GBP" }, { label: "USD", value: "USD" }]} ></DropdownMenu>
I'm glad for any tips :)
You have to use the onChange prop of react-select:
<select
id="dropdown-menu"
onChange={handleSelectChange}
>
and in this function you could handle the changes:
const handleSelectChange = (selectedVal) => console.log(selectedVal)
I recommend you using directly onChange and save it into a state:
1st:
Create state with the name you want:
const [selectValue, setSelectValue] = useState({});
2nd: Create options:
const options = [
{ label: "Tomate", value: 1 },
{ label: "Queso", value: 2 }
];
3rd: add method onChange in select and pass options:
const onChange = (ev) => {
setSelectValue(ev);
//console.log(ev);
console.log(selectValue);
};
<Select
id="dropdown-menu"
placeholder={"e"}
options={options}
onChange={onChange}
/>
I have created demo here:
https://codesandbox.io/s/ancient-pond-96h53?file=/src/App.js

Resources