We have a (TypeScript) class that manages a set of parameters (contains parameter type, default/min/max values, descriptions, ...) that we are using in quite a few places in our code.
For our GUI we have started to use React. One of the components we're building is essentially some kind of parameter property panel, and for the props of my component I would like to use our custom ParameterSet class.
Should this just work? Or do props need to be simple types?
Does React do internal things that will stop working properly when props contain custom classes that are more complex than simple types?
Just like #Rob has commented you, props can store whatever. You have to see them like an object that can have unlimited named references.
You can validate their types (if you want), which when running your app in development will let you know if these types are correct:
MyComponent.propTypes = {
element: React.PropTypes.element.isRequired,
}
You can watch for changes, see React lifecycle:
componentWillReceiveProps(newProps) {
// handle props change
}
Related
I've been reading about the advantages of using Context in React and I am unconvinced. I'm wondering if there's something I've missed.
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
What's the hassle in creating a props object in the main component and just passing it around among the underlings? Something like:
// do this once at top level (I'm assuming [foo, foo_set] and [bar, bar_set] are state variables):
const props = {foo, foo_set, bar, bar_set, thisAndThat, theOther, whatever, etcAndEtc}
// including one component
<MyComponent1 {...props } />
// including another
<MyComponent2 {...props } />
(Maybe better to use another name than props for this object, as the components can have other properties. Anyway.)
Then in MyComponent1 you can access all the props you want, or not access them. Either:
...
const MyComponent1 = (props) => {
...
// here we can use any props we need, props.bar, props.bar_set, props.theOther for example
const localVar = props.bar * 2;
props.bar_set(localVar);
// this changes the value of bar throughout the app
...
}
the advantage of the above, as I see it, is that you can pass around the props object to other sub-sub-components and not worry about whether you have anything missing.
Or:
...
const MyComponent1 = ({bar, bar_set, theOther }) => {
...
// here we can use bar, bar_set, theOther in the same example
const localVar = bar * 2;
bar_set(localVar);
...
}
The advantage of this option being that the syntax is shorter.
So my point is why not just use the standard JavaScript syntax? Why introduce new concepts when there are plenty to assimilate to do all sorts of other things?
Consider a fairly common case for most applications: You have authentication information (eg, the current user), a routing library (eg, react-router), and a theme object (what colors to use). These are needed in components scattered throughout the app.
You want to render a button somewhere down at the tip of the component tree. It's going to show the user's avatar, so it needs the authentication data. It's going to navigate when clicked, so it needs the navigate function from the routing library. And it needs to style itself according to the theme.
This certainly can be done through props, but in order for the button to get the props, every component in the chain above it must get and forward those props too. This could be many components deep, like page component -> section component -> table -> row -> widget -> button, and most of them don't need that information for themselves, so they're just taking the props in order to forward it along.
And you can easily imagine cases where there are more than 3 pieces of data that are needed across the app.
What's the hassle
Most people find this "prop drilling" to be a hassle, but let's assume you don't. You still have the problem that it has bad performance. If every component must receive the full set of "global" values that the app might need, then any time anything changes, the entire app must rerender. Optimizations like react.memo become effectively useless. You will get much better performance if you only pass the props you need.
Easier to edit code (You don't have to delete for example unused variable)
Better redability (You dont see unnescesary variables, and You see which component is using variables)
Lesser performance waste (preventing from consuming unnescesarry variables)
Suppose You got 10 descendants in - You would have to pass one variable through 10 of components.
What if some could have the same variable name ? You would have to edit Your passed variable for a while, then edit back later.
To sum up:
Using Context more efficient than stuffing everything into a single object variable, because it avoids re-rendering the whole app when anything changes.
People think passing a single variable around is more hassle than introducing specific syntax.
Context also allows you to have different values for the same variable in different parts of the app. This is shown here (the best explanation IMHO) : https://beta.reactjs.org/learn/passing-data-deeply-with-context
The above article also specifies that sometimes passing props is the best solution. It gives a list of use cases for context, and the advantages provided in each case.
I have been working in a react typescript project for awhile and the way that we had been type-checking props was with the React.FC generic. Going into the react typescript documentation I find code like the following:
interface DateProps {
iso8601Date: string;
message: string;
}
const DateComponent: FauxactFunctionComponent<DateProps> = props => (
<time dateTime={props.iso8601Date}>{props.message}</time>
);
However I just started a new project and there have been a few updates and we updated the eslint to the recommended for react. The new eslint rules are throwing the error:
"missing in props validation eslintreact/prop-types"
This can easily be avoided by following changing some linting rules recommended here:
"rules": {
"react/prop-types": "off"
}
I am tempted to turn off this linting rule and do it as we have done in the past. I don't think I see any added benefit from the docs. But am asking if there is something I am missing with the use of prop-types and why might it be better than the original method? I am leaning towards turning it off.
React PropTypes is a runtime check: in case of incorrect types / missing/extra props, you would get a runtime error in the browser console pointing out the discrepancy (besides possibly a crashing component in case of missing prop...).
It is useful when there is no static type check in the project, as described in the documentation:
For some applications, you can use JavaScript extensions like Flow or TypeScript to typecheck your whole application. But even if you don’t use those, React has some built-in typechecking abilities.
In your case, you use TypeScript for static type check of the props, it is very good at this job in almost every situation (minus very acute corner cases).
Besides, the main IDE's (in particular VS Code) have TSX support that leverage your prop type definition to validate them within the JSX syntax, as if it were a normal function call.
PropTypes also enables specifying default prop values; it is the main way to do so in class-based components. But with Function components, we can simply use JS default parameters (even when destructuring).
Therefore, in line with the docs, if you properly specify the TS types on your props, and use only Function components, there is need to double the work with React PropTypes, and you can safely disable this linter rule.
I'm creating a form builder using React.
The point is, everything is dynamic.
A form can have fields, or field groups. Each field group can have many fields. Each field can have it's own controls, hints, valdiations, etc.
This means that a form is a component hierarchy. A tree of components.
Now I want to know if in this tree, any Upload field exist at all.
Because if there is no Upload field, then I submit the form using application/json content type. Otherwise I would submit the form using application/form-data content type.
I know I can traverse the entire JSON of component props. But that seems very inefficient.
Is there a way to traverse React's component tree in an efficient way?
You can do so by using contextApi or with its hook for React Version > 16.8 the useContext.
Read more in React official docs
My suggestion is to use formik npm package to build your form correctly and easily, formik using context for managing the state behind the scene. I recommend it for regular use of forms, not heavy form with many fields (~25-30 max) like in enterprises.
You can read about formik more here:
https://formik.org/docs/api/formik
There is another alternative for formik which is also popular in react using forms:
react form hook: https://react-hook-form.com/
I didn't use it yet but as I know it has some pros/cons over formik.
Easiest way is vanilla JS.
const FORM_SELECTOR = '#some-form-id';
const UPLOAD_SELECTOR = '.some-upload-class';
const form = document.querySelector(FORM_SELECTOR)
if(form.querySelectorAll(UPLOAD_SELECTOR).length) {
// upload exists
} else {
// upload does not exist
}
Currently I have to do the following:
interface MyCompProps {
someAttr: number
}
I want to use aria-, and then I have to list upfront all aria-* I need. Furthermore, I can't set a simple className on the component. How can I avoid this, i.e. allow normal HTML attributes on component? Or is it a bad practice? I'm skimming the Advanced Guides on reactjs website and nowhere mention that this is a bad practice, so I think it is acceptable.
Note that all aria-* HTML attributes are fully supported in JSX. Whereas most DOM properties and attributes in React are camelCased, these attributes should be hyphen-cased (also known as kebab-case, lisp-case, etc) as they are in plain HTML
Docs
I'm very new to React and I'm trying to make a simple application that renders html controls.
I want to have an API that return array of json objects contains properties that determine the type and the value of each control like id, type, value ... etc.
Let's say that I have some controls like Input and Button.
What I'm thinking of is Creating a base class named HtmlControl that extends React.Component and other html controls should extend from the HtmlControl and finally a class for rendering these controls.
How can I be able to render the controls that extends only HtmlControl class ?
That would not be a good choice as react says you should not focus inheritance rather focus on containment or composition.
React has a powerful composition model, and we recommend using composition instead of inheritance to reuse code between components.
and
At Facebook, we use React in thousands of components, and we haven't found any use cases where we would recommend creating component inheritance hierarchies.
Props and composition give you all the flexibility you need to customize a component's look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions.
Please Visit this link to learn more.
You can create separate classes for each of the components or elements and combine them in one class like this:
import Button from './Button'
import Radio from './Radio'
import TextInput from './TextInput'
class HtmlComponent{
// note: we don't need to extend it from React.Component
// we will some function to render them.
renderTextInput() { <TextInput /> }
renderRadio() { <Radio /> }
}
// you can now use below code:
const hC = new HtmlComponent();
hC.renderTextInput();
Note Again this is not a nice idea to do but you can achieve your goal.