Why { ...arg} are used inside the components of react -daisyUi - r-daisy

Why {...arg} are passed inside the daisyUi component.
All components have internal {...arg} . But what does it do.
return <Button {...args} />
Another one
<Dropdown {...args}>
<Dropdown.Toggle>Click</Dropdown.Toggle>
<Dropdown.Menu className="w-52">
<Dropdown.Item>Item 1</Dropdown.Item>
<Dropdown.Item>Item 2</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
return <Swap {...args} />

It's a frustration of mine too. Their docs just aren't very good. Basically args is an object of props, and {...args} can be used to unpack that object, as though they were props to the component.
If we look at Dropdown, we could set the hover option like:
const args = {hover: true}
<Dropdown {...args}>
... //and so on
(More realistically probably from function props or something)
or like
<Dropdown hover >
... //and so on
Which to me is a lot more readable, but isn't as flexible if this is a part of a larger component or something.

Looks like, args is a Storybook thing.
Please check—
https://storybook.js.org
https://storybook.js.org/docs/react/writing-stories/args

Related

How to return multiple times same component but with independant state?

Hi guys in react i want to do something like render 2 times a component in same render function like this
const Main()=>{
const [names, setNames] = useState([]);
const [selected, setSelected] = useState(-1);
return(
<Component1 name={names[selected].name}
setName={setNames}/>
<Component1 name={names[selected].name}
setName={setNames}/>
)
}
This where i passed setNames from Main() to Component1 to handle state
and pass names from Main() then map it in select of Component1
<StyledSelect
ml="10px"
onChange={(e) => {
setName(e.target.value);
value={name}>
{names.map(({ name}) => {
return (
<option key={name} value={name}>
{name}
</option>
);
})}
my component has an html select that has names in it, when i choose one it trigger a it in database and retrieve name data (age, location), the problem is when i select name on my second Component1, it will also select the same name and retrieve same name data on my first Component1, and i want them to be independent. How ?
I tried to put key like that
return(
<Component1 key="compare" name={name}/>
<Component1 key="compared" name={name}/>
)
but nothing changes
Thanks
This question is worded incorrectly (this has nothing to do with state and everything to do with props and how React renders) and is missing information, but here are a few pieces of information that might help:
Keys don't change anything on the front-end; they are a tool React uses to improve performance on the back-end. Click here to read the docs for more information on keys and how React uses them.
React components are JavaScript functions and can therefore only return 1 thing. The code sample you shared would not work in React (or JavaScript). In order to return multiple items, it is possible to wrap them in an array or a React Fragment. Consider this example:
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
If you want to make the dropdowns different in appearance and/or functionality, the name prop will need to be different. Right now, both instances of Component1 are being given the same name property, which is why they probably look and behave identically.
(i would like can comment but i can't)
i am not sure (i must see the complete code) but i think that:
return(
<Component1 key="compare" name={name}/>
<Component1 key="compared" name={name}/>
)
must be
return(
<Component1 key="compare" name={name1}/>
<Component1 key="compared" name={name2}/>
)
this way they don't share the same variable
Where is it that you're making the call and setting the name? Since you're passing the same prop name to both of them they will be the same.
Either you set name inside Component1 itself or you make a different state for each Component1.

Using Stateful React classes in typescipt

I am trying to create a Stateful class in which you can call methods such as createHeaderButton() where after calling it would update the state and re-render with these new updates in the component.
Im using Material-UI and so most of their styling utilizes Reacts hook API which of course classes cant use. Ive tried to get around this by using;
export default withStyles(useStyles)(HeaderBar)
Which exports the class separately with the Styles(withStyles(useStyles) useStyles as the defined styles) And the class(HeaderBar). Now the only issue is that i need to access the styles in my class. Ive found a JS example online that wont work for me because of the strong typed syntax of TS. Additionally When initializing my Class component in other places i try to get the ref=(ref:any)=>{} And with that call the create button methods when i get a response from my server, Which doesnt work because of this new way of exporting the class component!
Thanks for the help, Heres my component class: https://pastebin.pl/view/944070c7
And where i try to call it: https://pastebin.com/PVxhKFHJ
My personal opinion is that you should convert HeaderBar to a function component. The reason that it needs to be a class right now is so you can use a ref to call a class method to modify the buttons. But this is not a good design to begin with. Refs should be avoided in cases where you can use props instead. In this case, you can pass down the buttons as a prop. I think the cleanest way to pass them down is by using the special children prop.
Let's create a BarButton component to externalize the rendering of each button. This is basically your this.state.barButtons.forEach callback, but we are moving it outside of the HeaderBar component to keep our code flexible since the button doesn't depend on the HeaderBar (the header bar depends on the buttons).
What is a bar button and what does it need? It needs to have a label text and a callback function which we will call on click. I also allowed it to pass through any valid props of the material-ui Button component. Note that we could have used children instead of label and that's just down to personal preference.
You defined your ButtonState as a callback which takes the HTMLButtonElement as a prop, but none of the buttons shown here use this prop at all. But I did leave this be to keep your options open so that you have the possibility of using the button in the callback if you need it. Using e.currentTarget instead of e.target gets the right type for the element.
import Button, {ButtonProps as MaterialButtonProps} from "#material-ui/core/Button";
type ButtonState = (button: HTMLButtonElement) => void;
type BarButtonProps = {
label: string;
callback: ButtonState;
} & Omit<MaterialButtonProps, 'onClick'>
const BarButton = ({ label, callback, ...props }: BarButtonProps) => {
return (
<Button
color="inherit" // place first so it can be overwritten by props
onClick={(e) => callback(e.currentTarget)}
{...props}
>
{label}
</Button>
);
};
Our HeaderBar becomes a lot simpler. We need to render the home page button, and the rest of the buttons will come from props.childen. If we define the type of HeaderBar as FunctionComponent that includes children in the props (through a PropsWithChildren<T> type which you can also use directly).
Since it's now a function component, we can get the CSS classes from a material-ui hook.
const useStyles = makeStyles({
root: {
flexGrow: 1
},
menuButton: {
marginRight: 0
},
title: {
flexGrow: 1
}
});
const HeaderBar: FunctionComponent = ({ children }) => {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<HeaderMenu classes={classes} />
<Typography variant="h6" className={classes.title}>
<BarButton
callback={() => renderModule(<HomePage />)}
style={{ color: "white" }}
label="Sundt Memes"
/>
</Typography>
{children}
</Toolbar>
</AppBar>
</div>
);
};
Nothing up to this point has used state at all, BarButton and HeaderBar are purely for rendering. But we do need to determine whether to display "Log In" or "Log Out" based on the current login state.
I had said in my comment that the buttons would need to be stateful in the Layout component, but in fact we can just use state to store an isLoggedIn boolean flag which we get from the response of AuthVerifier (this could be made into its own hook). We decide which buttons to show based on this isLoggedIn state.
I don't know what this handle prop is all about, so I haven't optimized this at all. If this is tied to renderModule, we could use a state in Layout to store the contents, and pass down a setContents method to be called by the buttons instead of renderModule.
interface LayoutProp {
handle: ReactElement<any, any>;
}
export default function Layout(props: LayoutProp) {
// use a state to respond to an asynchronous response from AuthVerifier
// could start with a third state of null or undefined when we haven't gotten a response yet
const [isLoggedIn, setIsLoggedIn] = useState(false);
// You might want to put this inside a useEffect but I'm not sure when this
// needs to be re-run. On every re-render or just once?
AuthVerifier.verifySession((res) => setIsLoggedIn(res._isAuthenticated));
return (
<div>
<HeaderBar>
{isLoggedIn ? (
<BarButton
label="Log Out"
callback={() => new CookieManager("session").setCookie("")}
/>
) : (
<>
<BarButton
label="Log In"
callback={() => renderModule(<LogInPage />)}
/>
<BarButton
label="Sign Up"
callback={() => renderModule(<SignUpPage />)}
/>
</>
)}
</HeaderBar>
{props.handle}
</div>
);
}
I believe that this rewrite will allow you to use the material-ui styles that you want as well as improving code style, but I haven't actually been able to test it since it relies on so many other pieces of your app. So let me know if you have issues.

React (not sure where a variable comes from)

I am new to React and am trying to understand React-Popper. This is some code from
https://www.npmjs.com/package/react-popper
Where are the values for 'ref', 'style', 'placement' and 'arrowProps' coming from and how would I edit them? I understand that you can use this.props and attributes to pass values to Components but i dont understand where the values to be inserted into the function is coming from.
import { Manager, Reference, Popper } from 'react-popper';
const Example = () => (
<Manager>
<Reference>
{({ ref }) => (
<button type="button" ref={ref}>
Reference element
</button>
)}
</Reference>
<Popper placement="right">
{({ ref, style, placement, arrowProps }) => (
<div ref={ref} style={style} data-placement={placement}>
Popper element
<div ref={arrowProps.ref} style={arrowProps.style} />
</div>
)}
</Popper>
</Manager>
);
What you're seeing here is an arrow function being combined with destructuring assignment and React Render Props. So it's a lot in one code example.
From your question, I think what's confusing you most is the destructuring assignment. So here is an example which I hope will help you:
var foo = ({a, b}) => a + b;
var x = {
a: 1,
b: 2
};
console.log(foo(x));
# Output is 3
This is because destructuring assignment assigns the values from the object into the variables a and b as if they were function parameters. The same thing is happening with the props object on the React components and that's why you don't see props.ref, etc.
They are render props for the Popper component. They are all parameters of the render prop function defined in the Popper file you can find on the GitHub for this package. I'm not familiar with this specific library, but basically they are being passed to that function, and they need to be there as it's defined or it will throw an error. You should be able to compute your own values for styles and whatnot but again I'm not familiar with this package.

Passing components into another in react

I have an app with a number of components. One of the components I need be to able to pass different variations of another two components into, based on a layout. I believe it can be passed in like a data attribute, but I'm unsure of the exact syntax to push the other components in.
Given two components <List /> and <Box /> which are currently in another component being imported into my main App.js file as such:
export const CallOut = () => {
return(
<div style={styles.sectionInner}>
<List />
<BoxRight/>
</div>
)
};
where <CallOut /> is being imported into App.js, I'd like to pass those two components into the <CallOut /> component.
What is the correct syntax to pass those two in and have them placed in the same spot they're currently in within the CallOut component?
I believe it should be something similar to
<CallOut param={List} param={BoxRight} />
but I know this isn't right.
You can use capital names for props, and use these to instantiate react components like this:
export const CallOut = ({List, Box}) => (
<div style={styles.sectionInner}>
<List/>
<Box/>
</div>
);
List and Box are the properties of this component. You can instantiate it like this:
<CallOut List={SomeComponent} Box={SomeOtherComponent}/>
I don't know if we're on the same page but maybe you're looking for children property ?
So your component will look like that:
export const CallOut = ({children}) => (
<div style={styles.sectionInner}>
{children}
</div>
);
And usage:
<CallOut >
<List/>
<Box/>
</CallOut>
You can pass any component as CallOut child or even do some filtering using children API
It's common usage when components don’t know their children ahead of time and it's used just for some kind of boxing/wrapping.

What is a good practice to avoid duplicated functions in React.js with 'this.setState' format?

I have the following code:
#autobind
setName(name){
this.setState({name: name});
}
#autobind
setLocation(location){
this.setState({location: location});
}
#autobind
setReference(reference){
this.setState({reference: reference});
}
All the functions placed above have a similar structure, and I would like to know if there is a good practice in React.js to avoid having to repeat myself to set different states.
Thanks in advance.
You could make a function that takes the object as a value, rather than the key value and pass it to setState
setValue(object) {
this.setState(object)
}
and use it like:
<div onClick={() => this.setValue({ reference })} />
but then you may as well just call setState directly.
<div onClick={() => this.setState({ reference })} />
So really you don't need any of those functions because setState is that function.
However, this generalized setValue function could be useful when passing to children.
<Child setParentState={this.setValue} />
and use it
<div onClick={() => this.props.setParentState({ reference })} />
Though I admit I've never done anything like that. Seems to give too much control to child elements, but used sparingly should be fine.

Resources