After going through the document of #material-ui I got stuck in the #material-ui/styles section with some question wanting to ask?
Which one of these 3 (Higher-order component, Styled components or Hook) is the best in practice to implement with React. Should I use Hook API from Material-UI with React Hook to have best result when styling with Material-UI? Because I'm currently adopting Hook in React.
I came across these few line of codes and can't understand, please help me with syntax. This can found in the Adapting the hook API
̣̣(https://material-ui.com/styles/basics/#adapting-the-hook-api)
function MyButton(props) {
const { color, ...other } = props;
const classes = useStyles(props);
return <Button className={classes.root} {...other} />;
}
What will ...other be? And then why it is in the <Button/>?
Best Regards,
Related
I'm learning reasonml and quite excited about it. Something I often do in typescript react code is:
type Props = React.HTMLProps<HTMLButtonElement> & { foo: boolean }
const SuperButton: React.FC<Props> = (props) => <button {/* stuff with props */ />
In this regard, I communicate to my users as a component library provider that this button extends normal HTML button attributes.
How can I express and extend normal html component attributes in my components?
I see that reason explicitly doesn't support spreading props: https://github.com/reasonml/reason-react/blob/master/docs/props-spread.md.
I do see that there is a composition strategy: How to compose props across component in reason-react bindings?, but not sure how to marry that up with normal HTML element component stuffs.
Any recommendations? Thanks!
It's possible to do something similar using ReasonReact.cloneElement, as Amirali hinted. The idea is to split up your component's props and the HTML button's props into two separate parameters for your component, render your button, and then clone it while also injecting the extra button props.
This page shows a component which encapsulates this clone-and-injection functionality:
module Spread = {
[#react.component]
let make = (~props, ~children) =>
ReasonReact.cloneElement(children, ~props, [||]);
};
Now, you can use this Spread component for your SuperButton component:
module SuperButton = {
[#react.component]
let make = (~foo, ~htmlButtonProps) =>
<Spread props=htmlButtonProps>
<button> (foo ? "YES" : "NO")->React.string </button>
</Spread>;
};
The htmlButtonProps prop will contain the regular HTML button props, while separately foo is your component's specific prop. The component can be used like this:
<SuperButton foo=true htmlButtonProps={"autofocus": true} />
Small housekeeping note: you don't actually need to define the modules with the module keyword. If you want you can put them in separate files called Spread.re and SuperButton.re. Reason files automatically become modules.
I have a custom component and would like to apply the exact same styles as the <Typography> component gets when setting the noWrap prop. The following does work:
<span className="MuiTypography-noWrap">
But there's of course no actual type-checking or "link" to anything here, which means if the name ever changes or is removed in a future version, I won't get any type/build error from it.
Is there a "Material UI way" to reuse/copy these classes? E.g. is there somewhere I can import/access these names from?
I assume you have a reason, but given your example of a span element, I can't help but wonder why you're not just using the MUI component.
I've never done this before, but I was curious and the styles are indeed exported. Not sure if this is a good idea or if there is another way...
import { styles } from '#material-ui/core/Typography/Typography';
const noWrapStyles = styles(theme).noWrap;
I'm trying to use the Grid component but I can't find out how to use the CSS API. Ths docs doesn't help me. I just don't get it..
Can someone please help me ?
I know this is not a really good place, sorry, but I can't find any answer anywhere confused
Ideally, you'd set direction to row and override the direction-xs-row class with the name of a class you define (which would set direction to column-reverse), but there are no classes exposed for overriding row for any breakpoint.
You could go the other way, setting direction to column-reverse and overriding direction-*-column-reverse (for all other breakpoints), but that would be tedious and somewhat insane.
The only way to do this at the moment would be to set the className prop to apply some responsive styling via JSS and withStyles:
// create a class that will set flex-direction for the xs breakpoint
const styles = theme => ({
[theme.breakpoints.down('xs')]: {
responsiveDirection: {
flexDirection: 'column-reverse',
},
},
});
// use withStyles to make the class available via the `classes` prop
export default withStyles(styles)(InteractiveGrid);
Then pass your class name, classes.responsiveDirection in this example, as the Grid's className prop:
{/* we would normally destructure classes from this.props */}
<Grid
container
className={this.props.classes.responsiveDirection}
>
Check this codesandbox for a working example.
I am learning on React JS and I have got information on JSX and babel. But I am not getting clarity on how these are helping React and how these or differ from each other
React JS
while building an app using React, you can create the components/views in two ways
using standard React object and methods
using JSX
JSX
JSX is a separate technology from React and completely optional while building React application, however it makes life much easier when you combine JSX with React.
Let's see how :
Approach 1 : standard React way
(function() {
var element = React.DOM.div({}, "Hello World");
ReactDOM.render(element, document.getElementById("app"));
})();
The above code can be found at this link.
Here, you just need to include the react and react-dom library to your page.
Nothing else is required. No JSX, no Babel.
Approach 2 : JSX way
(function() {
var HelloWorld = React.createClass({
render : function() {
return (
<div> Hello World </div>
);
}
});
var element = React.createElement(HelloWorld, {});
ReactDOM.render(element, document.getElementById("app"));
})();
The above code can be found at this link.
Note the difference here: <div> Hello World </div> is used inside JavaScript. This is called JSX syntax.
Now, compare the JSX approach with the vanilla JavaScript approach:
With JSX, You can add many more HTML like elements inline, just like standard HTML, to create the view layer.
Without JSX, the code can get messy because of the multiple layers of elements required to create HTML in JavaScript.
Babel
Now the question is, who understands JSX?.
Here We need a transpiler that understands JSX and converts it to a format that can run on browser. Babel does just this job.
Transpiling
Transpiling can be done two ways
Browser based/client side transpiling (use only for development
purpose)
include this file as a script tag
use type="text/babel" on your script tag which loads your JSX
Here's the sample code
Server based transpiling - e.g. Babel
You can use different tools like webpack etc.
Here's some sample code.
Hope this helps.
tl;dr;
JSX is an easy syntax to represent markup in your code, which Babel converts to pure JavaScript.
Long version:
JSX is a syntactical convention which aims to make element structure definition easier in a React Component's code. This XHTML-like syntax which you write inside your components gets converted into JavaScript (not very different from Hyperscript) by Babel.
A very simple Hello World component written in JSX:
class HelloWorld extends Component{
render(){
return <div><h1>Hello World!</h1></div>
}
}
And the equivalent in pure JavaScript:
class HelloWorld extends Component{
render(){
return React.createElement(
"div",
null,
React.createElement(
"h1",
null,
"Hello World!"
)
);
}
}
Do note that the above example is abbreviated to keep the focus on the JSX part.
You would soon learn that Babel actually lends a lot more power to the React world than mere JSX transpilation. It allows you to use a lot of cool new ES6/7 features right now.
The CollapsiblePanelExtender seems primarily designed to collapse/expand things in response to user mouse events. Is there also a good way to get the extender to collapse/expand things in response to client-side javascript?
In my particular case, I have a number of CollapsiblePanelExtenders (and their corresponding Panels) on a page, and I'm wondering if I could implement an "expand all panels" button by doing something like this strictly on the client side:
for each CollapsiblePanelExtender on this page, call somethingOrOther(extender)
I can implement this logic server-side instead if I did a full postback, but my page takes a long time to load, and so this doesn't seem like it would provide a very slick user experience. Thus I am interested in doing expand/collapse client-side.
It seems like this isn't a use case the AJAX Control Toolkit people had in mind, but I thought I'd check.
Write the following code in the OnClick event of Image/button
<asp:Image ID="img1" runat="server" OnClick="ExpandCollapse()"/>
function ExpandCollapse() {
$find("collapsibleBehavior1").set_Collapsed(true);
$find("collapsibleBehavior2").set_Collapsed(true);
}
Hope this helps!
I have a partly working solution now.
I followed Ian's suggestion and looked through the toolkit source. In CollapsiblePanelBehavior.debug.js, you can that expandPanel() is apparently intended as part of the public interface for the behavior. There's also a get_Collapsed(). The key to accessing these behaviors in javascript seems to be setting the BehaviorID property on your CollapsiblePanelExtender tags in ASP.NET.
I modified the repeater on my page so that the BehaviorIDs are predictible, along these lines:
<ajaxToolkit:CollapsiblePanelExtender
BehaviorID="<%#'collapsebehavior'+DataBinder.Eval(Container.DataItem,'id')%>"
ID="CollapsiblePanelExtender" runat="server" />
This results with behaviors named collapsebehavior1, collapsebehavior2, collapsebehavior3, etc..
With this done, I'm able to expand all the collapsible panels on the client as follows:
function expandAll() {
var i = 0;
while (true) {
i++;
var name = 'collapsebehavior' + i;
var theBehavior = $find(name);
if (theBehavior) {
var isCollapsed = theBehavior.get_Collapsed();
if (isCollapsed) {
theBehavior.expandPanel();
}
} else {
// No more more panels to examine
break;
}
}
}
I'm sure using $find in a loop like that is really inefficient, but that's what I have so far.
Also, it doesn't work on Firefox for some reason. (On FF only the first element expands, and then there's a Javascript error inside the Control Toolkit code.)
This will all seem extremely ugly to all you javascript pros. Maybe I'll clean things up later, or you can help me out.
You can also just toggle the panels to switch between collapsed/expanded states:
function toggle() {
var MenuCollapser = $find("name");
MenuCollapser.togglePanel();
}