I'm relearning react, I've done tons and tons of angular I ran the following command :
generate-react component carousel
(I'm using generate-react-cli)
this works well and generates the following .tsx file (plus test, lazy-loading and style files, which I am omitting) :
import React from 'react';
import styles from './carousel.module.scss';
const carousel: React.FC = () => (
<div className={styles.carousel}>
carousel Component
</div>
);
export default carousel;
this loads fine in my app but now I want to add actual code, functions.
I can't seem to do this.
I've broken open this const like so :
const carousel: React.FC = () => {
constructor(props) {
super(props);
}
componentDidMount() {
}
return (
<div className={styles.carousel}>
carousel Component
</div>
);
}
I assume this is where the constructor and so on go,
however in this area the constructor name and ect. is not allowed.
so I tried changing the type to React.Component
however at that point I get an error directly on the const name stating :
TS2740: Type '() => Element' is missing the following properties from
type 'Component{}, {}, any>': context, setState, forceUpdate, render,
and 3 more.
I'm really shooting in the dark here and reacts docs are antithetical to examples. they refuse to help with any of this.
I want this newer, shorthand syntax but I also want to be able to use lifecycles and functions.
As it turns out the correc syntax for this is as follows :
class carousel extends React.Component {
componentDidMount() {
console.log('hello');
}
render() {
return (
<div className={styles.carousel}>
carousel Component
</div>
);
}
}
Related
It's been a long while since I've done anything with React, not to mention I haven't done much of it in sharepoint. I used the yeoman generator to create a simple react app and now I am having trouble trying to wire up state.
The following code generates this error: Property 'show' does not exist on type 'Readonly<{}>'.
There are several other posts about what causes this but I haven't been able to successfully fix it in my app. It seems as though the generator creates and references the props file. I saw one post that said that I need to create (and reference) a similar file for state? I tried still couldn't get it to work. Any help would be GREATLY appreciated.
import * as React from 'react';
import styles from './SpetSelfServiceQuestionnaire.module.scss';
import { ISpetSelfServiceQuestionnaireProps } from './ISpetSelfServiceQuestionnaireProps';
import { escape } from '#microsoft/sp-lodash-subset';
export default class SpetSelfServiceQuestionnaire extends React.Component<ISpetSelfServiceQuestionnaireProps, {}> {
constructor( props ) {
super( props );
this.state = { show: true }
this.toggleDiv = this.toggleDiv.bind(this)
}
toggleDiv = () => {
const { show } = this.state;
this.setState( { show: !show })
}
React.Component<ISpetSelfServiceQuestionnaireProps, {}>
The second parameter to the generic is the type of the state. You've said that the state will be an empty object, so when you try to do something else, typescript points out the mismatch.
Looks like you want the state to be this:
interface ISpetSelfServiceQuestionnaireState {
show: boolean;
}
export default class SpetSelfServiceQuestionnaire extends React.Component<
ISpetSelfServiceQuestionnaireProps,
ISpetSelfServiceQuestionnaireState
> {
//...
}
It doesn't need to be in another file, unless you want it to be.
I need to change the style of some child components of a react components. Something like this:
import React, { Component } from 'react';
class Parent extends Component {
onClickHandler = (event) => {
this.props.children[0].props.style.marginLeft = "-100%";
}
render() {
<div onClick={this.onClickHandler}>
{this.props.children}
</div>
}
}
export default Parent;
The error i'm getting is:
TypeError: Cannot add property marginLeft, object is not extensible
May you help me guys?
Thanks a lot !!
The error you are getting is because you cannot modify props, since those are immutable. A simpler approach can be done using plain CSS and simple state management.
With this technique, you need a state variable to know when to add the class modifier. That class modifier is in charge of overriding the styles of the child component.
The JS would look like this:
import React, { Component } from "react";
class Parent extends Component {
constructor() {
this.state = {
bigMargin: false
};
}
onClickHandler = (event) => {
event.preventDefault();
this.setState({ bigMargin: true });
};
render() {
return (
<div className={`parent-class ${bigMargin && 'big-margin'}`} onClick={this.onClickHandler}>
{this.props.children}
</div>
);
}
}
export default Parent;
And the CSS can be something as simple as this (or as complex as you may want)
.big-margin:first-child {
margin-left: -100%;
}
React props are immutable and you can't change them, they are read only and you can't add new properties.
This is done via Object.preventExtensions, Object.seal and Object.freeze.
To "fix" the error partialy you should define marginLeft in the first child of your Parent component
<Parent>
<p style={{marginLeft: '0'}}>1</p>
<p>2</p>
</Parent>
You will get now a new Error :
TypeError: "marginLeft" is read-only
Imagine having the ability to change props, and you pass the same prop to many children, one of them change it value, this will lead to unexpected behavior.
Try something like
Grab the element by its id on click
document.getElementById("demo").style.marginLeft = '-100px'
Or use react refs to grab the element
I am trying to use https://www.npmjs.com/package/react-alert in my project, but the examples are porvided for the React components that are declared as functions but my React components are declared as classes like:
class ConnectedOrderForm extends Component {
//const statusAlert = useAlert();
constructor(props) {
super(props);
}
render() {
return (
<div>Test</div>
)
}
}
const OrderForm = withRouter(connect(mapStateToProps, mapDispatchToProps)(ConnectedOrderForm));
export default OrderForm;
When I am trying to call useAlert().show('OK'); from class event, I am getting:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
So, how can I use this react-alert hook from ES6 class component?
The solution was to use either export code:
const OrderForm = withRouter(connect(mapStateToProps, mapDispatchToProps)(ConnectedOrderForm));
export default withAlert()(OrderForm);
const OrderForm = withAlert()(withRouter(connect(mapStateToProps, mapDispatchToProps)(ConnectedOrderForm)));
export default OrderForm;
And call:
this.props.alert.show()
Based on the docs it would seem that you should not be using the useAlert hook but rather the withAlert HOC. Hooks can only be used in functional components, and since you want to use a class, you would need to the withAlert HOC.
Here is an example of that that would look like
import { withAlert } from 'react-alert'
class App extends React.Component {
render() {
const alert = this.props.alert;
return (
<button
onClick={() => {
alert.show('Oh look, an alert!')
}}
>
Show Alert
</button>
);
}
}
export default withAlert()(App)
Did you try this one?
import {alert} from 'react-alert';
alert.show('Some message', {
... options
})
UPD. Sorry, this is wrong answer, Please take a look here:
https://github.com/schiehll/react-alert/issues/116
Im following a React Native course and at some point the teacher defines a component as constnat using the following code:
const Comment = (props) =>
<Text>{props.text}</Text>
However I dont manage to make it work. I made a snack to just try the component individually and it doesnt work: https://snack.expo.io/S1eKSeV-7
I always get the error Invariant Violation: element type is invalid.
What Im doing wrong?
You are not exporting your component. That is why you get the error because Comment component is undefined.
import React from 'react'
import {Text} from 'react-native'
const Comment = (props) =>
<Text>{props.comment.text}</Text>
export default Comment
This is a functional component. There are two type of components in React: Functional and class components. If you don't need any state or don't use any lifecycle methods in your component you can and should use functional components.
Functional components
const SomeComponent = () => <div>Something</div>;
No need to use an explicit return here since arrow function do this for us if there is one single statement.
With regular function:
function SomeComponent() { return <div>Something</div> };
Class components
class SomeComponent extends React.Component {
state = { foo: "bar" };
someLifeCycleMethod() {
....
}
render() {
return( <div>Something</div>);
}
}
When you don't understand something always refer to official documentation.
The problem you are having is not directly related to component type. As suggested in another answer your component probably is not exported.
This will work:
const Comment = (props) => {
return (
<Text>{props.text}</Text>
);
};
Let's say there's a React component that I like, but want to modify. For this example, we'll use Material UI's LinearProgress. I want to make a clickable seek bar out of it.
class SeekBar extends LinearProgress {
componentDidMount() {
super.componentDidMount();
console.log('my stuff here');
}
}
But I feel like I might be very limited as to what I can do as far as changing what render returns. Maybe I'm going about this all wrong, though. If I like a particular React component such as a Material UI component, what is a good, reusable way to customize its look and functionality and make it my own?
In the ES6/JSX/React world, you can extend component behaviors and values in many ways. I'd recommend one of the following, considering that you use Material UI.
First case:
You have two components that extend the Component from React:
class ExampleComponent extends React.Component {
render () {
return(
<div>
<button {...this.props}>
Click me!
</button>
</div>
)
}
}
class RenderComponent extends React.Component {
clickHandler () {
console.log('Click fired!')
}
render () {
return(
<ExampleComponent onClick={this.clickHandler.bind(this)} />
)
}
}
In that example, onClick is passed via props inside the rendered ExampleComponent. Example here.
Second case:
This is similar on how Material UI extends their own components:
class ExampleComponent extends React.Component {
clickHandler () {
console.log('Click fired!')
}
}
class RenderComponent extends ExampleComponent {
render () {
return(
<div>
<button onClick={this.clickHandler.bind(this)}>
Click me!
</button>
</div>
)
}
}
In this example, you have one component that extends Component from React but only has event methods. Then, you extend this component and render your own with the extended behavior. Here is a live example.
Hope it helps!
One way is:
export default class Seekbar extends React.Component{
// perform any modification
render(){
return <LinearProgress ...changes/>
}
}
Another way is a Higher Order Component, HOC. Here's a great blog with more info: http://natpryce.com/articles/000814.html
I think with Material-UI your best bet would be to wrap it and make any modifications you'd like. Unfortunately this project is very tightly coupled thanks to things like inline styles and their thememanager so taking a single component out may be difficult. HOC would be better for things like sharing some smart functionality across components, like passing a "theme" prop automatically to components.