I got an app that is working on react using a class component, i found a code of a feature that i would like to add to my code but it's made using a functional component. The code is here https://codesandbox.io/s/framer-motion-animate-in-view-gqcc8 but the relevant part is this.
import { useInView } from "react-intersection-observer";
import { motion, useAnimation } from "framer-motion";
import "./styles.css";
function Box() {
const controls = useAnimation();
const [ref, inView] = useInView();
useEffect(() => {
if (inView) {
controls.start("visible");
}
}, [controls, inView]);
I don't know how to add that controls variable in my class component
class App extends Component {
constructor(props) {
super(props);
this.state = {
curtains: null,
loading: true,
renderNav: false
};
}
Should i add it on my state? i don't understand how to make it works in class component
You can't use hooks inside of a class component. What you can do is to write a little wrapper that exposes the ref and controls in a render prop:
const Controls = ({children}) => {
const controls = useAnimation();
const [ref, inView] = useInView();
useEffect(() => {
if (inView) {
controls.start("visible");
}
}, [controls, inView]);
return children(ref, controls);
};
Then you can use it like this:
class App extends Component {
// ...
render() {
return (
<Controls>
{(ref, controls) => (
<motion.div ref={ref} animate={controls}>
{/* content */}
</motion.div>
)}
</Controls>
);
}
}
Lets say you have
const functionalComponent=()=>{
return <h1>Functional componenet</h1>
}
and you want to change it to class component
use this import at the top:
import React,{Component} from "react";
and change your code to something like this:
Class functionalComponent extends Component{
state={}
render(){
return <h1>functional component</h1>;
}
}
your functional component is now changed to class component.
And to use it in your existing class component , you don't need to change your functional component to class component unless you require local state.
with the introduction of react hooks that's also changed i.e, you don't have to change your functional component to class component if you plan to use hooks.
In your code : useEffect is a hook and you can't use it inside a class component.
I would recommend simply importing the functional component inside your class component and if you have to pass some value , you can pass it as a prop.
And as far as importing your functional component is concerned:
import React,{Component} from "react";
import Box from "./Box.js";
class App extends Component {
constructor(props) {
super(props);
this.state = {
curtains: null,
loading: true,
renderNav: false
};
render(){
return(<Box/>);
}
}
You can also use functional components anywhere like a class component. Btw is also using so no need to worry about the thing that you cannot use state in it.
Use:
<Box props={props}/>
Related
So I have a file called Context.js which looks like the following:
const AppContext = createContext({
// ... scheme colour palette
color1: '#ADBDDB',
color2: '#7F8EB2',
color3: '#546287',
color4: '#384366',
// ... grey colour palette
grey1: '#FFFFFF',
grey7: '#2A3033',
// ... Nexus back-end constants
nexusIP: '126.0.0.2',
I want to import that file onto another component and use the "nexusIP" in that component. However, it is giving me issues. This is what I tried to do:
import Context from '../context/AppContext';
import React, { useContext, useState , Component } from 'react';
const { nexusIP, color5, grey1 } = useContext(AppContext);
class TempsAndTime extends React.Component {
constructor(props){
super(props);
this.state = {
bedTempDisplay: props.bedTemp,
bedTempUser: props.bedTemp,
hotEndTempDisplay: props.hotEndTemp,
hotEndTempUser: props.hotEndTemp,
pcBootTimeStamp: props.pcBootTimeStamp,
pcId: props.pcId,
hotEndTempCondition: null,
bedTempCondition: null
}
}
render() {
const { classes } = this.props;
let bedTempIcon;
let hotEndTempIcon;
return (
<div className={classes.container} >
<div className={classes.timeContainer} >
<Typography className={classes.timeElapsed}>
Time elapsed
</Typography>
</div>
<div>
);
}}
So I tried to destructure the value from that other Context.js file into this file but it was not letting me to do so. Any ideas?
according to React documentation you can't use hook inside a class component nor outside of a functional component. so, try with functional component and definitely call inside the component, otherwise consume the context as React suggest with render props
I am not really sure how to properly ask this question but I will explain what I'm trying to do here:
So I have this parent Component which creates a Component like so:
<CurrentTemperature cityName={this.state.cityName}></CurrentTemperature>
The CurrentTemperature Component looks like this:
import React, { Component } from "react";
import "../App.css";
export default class CurrentTemperature extends Component {
constructor(props) {
super(props);
this.state = {
temperature: 0,
cityName: this.props.cityName,
};
}
componentDidMount() {
//fetch the temperature from api here
}
render() {
return (
<div>
<div className="city-temperature">
{this.state.cityName} {this.state.temperature}
</div>
</div>
);
}
}
All I'm trying to do is read the city name from the parent, then fetch the current temperature from my API, and then display both of those in the Component. But if I try to console.log(this.props.cityName) from anywhere other than from inside the city-temperature div, I always get an empty string. What is going on here?
cityName is the state of the parent component. I guess the parent component would get the "cityName" asynchronously. right? If this is the case, You have to put the temperature in the parent component as its state. And you have to insert the API call in the parent component. CurrentTemperature component will behave like a pure function component.
const CurrentTemperature = ({temperature, cityName}) => {
return (
<div className="city-temperature">
{cityName} {temperature}
</div>
);
}
I guess this is not only the solution but also the best DX.
You can remove this in your constructor, and then use this.state.cityName
constructor(props) {
super(props);
this.state = {
temperature: 0,
cityName: props.cityName,
};
}
I have a Component like this:
class GlobalComponent extends React.Component{
select= (e) => {
this.props.select(); // must be implemented in another component and not parent
};
render(){
return(
<div>
{this.state.data}
<Button onClick={this.select}>Select</Button>
</div>
);
}
}
function mapStateToProps(state) {
return state.data
}
const mapDispatchToProps = (dispatch, props) => ({
select: () => dispatch(select()),
});
export default connect(mapStateToProps, mapDispatchToProps)(GlobalComponent );
I am importing this component in the root of my app - app.js like this:
<GlobalComponent />
The problem is this actionselect. I know I can pass it from global state or parent component with props (for the example):
<GlobalComponent select={this.select} />
or with mapDispatchToProps
, but the problem is that the component is defined only in one place, otherwise I need to import the GlobalComponent in almost all components.
What I want is to import the component once (somewhere in the root) and then somehow in a component that uses GlobalComponent define a function, which will NOT execute select, but implement select and it is only for the click event in the GlobalComponent:
export default class ComponentThatUsesGlobal extends React.Component {
executeWhenGlobalComponentBtnIsClicked = () => {
}
}
Is this possible and is it good approach or it is better just to import the component everywhere ?
I am using and Redux.
I'm trying to implement methods to the React import of PESDK (PhotoEditorSDK).
I have an App.js that imports Header, BodyLeft and BodyMiddle without relation between them.
BodyMiddle.js is a template component that renders :
// src/components/BodyMiddle/index.js
import React, { Component } from "react";
import "./BodyMiddle.css";
class BodyMiddle extends Component {
constructor(props){
super(props);
}
handleClick(e) {
e.preventDefault();
// Nothing yet
}
render() {
return (
<div id="BodyMiddle">
<div><button id="resetEditor" onClick={(e) => this.handleClick(e)}>Reset Editor</button></div>
<div class="photo-editor-view"></div>
</div>
);
}
}
export default BodyMiddle;
PhotoEditor.js is the component that calls the PESDK :
// src/components/PhotoEditor/index.js
import React from 'react'
import ReactDOM from 'react-dom'
window.React = React
window.ReactDOM = ReactDOM
import "./PhotoEditor.css";
import "photoeditorsdk/css/PhotoEditorSDK.UI.ReactUI.min.css";
import PhotoEditorUI from 'photoeditorsdk/react-ui'
class PhotoEditor extends React.Component {
constructor(props){
super(props);
}
resetEditor(){
// Empty the image
return this.editor.ui.setImage(new Image());
}
render() {
const { ReactComponent } = PhotoEditorUI;
return (
<div>
<ReactComponent
ref={c => this.editor = c}
license='licence_removed_for_snippet'
assets={{
baseUrl: './node_modules/photoeditorsdk/assets'
}}
editor={{image: this.props.image }}
style={{
width: "100%",
height: 576
}} />
</div>)
}
}
export default PhotoEditor;
Note that the photo-editor-view div class is rendered in BodyLeft.js, by calling the following code and it works well:
ReactDOM.render(<PhotoEditor ref={this.child} image={image} />, container);
Where container is (and I pass an image somewhere else) :
const container = document.querySelector('.photo-editor-view');
What I'm trying to achieve
I would like to keep the reset Button inside BodyMiddle, which is independant and called from App.js, in order to call the PhotoEditor component on the method resetEditor() from anywhere in my app.
That way I could have separated template files that interract with each other.
I've done research and I did not really find an answer yet, I know that React might not be the lib for that, but what are the options ? I see more and more React live apps running with a lot of components interacting, I'm curious.
Thank you for your time !
Best regards
You can use ref on PhotoEditor and save that ref in App, and in the App you can have a method called onResetEditor which calls the ref.resetEditor.
Now you can pass onResetEditor to BodyMiddle or any other component.
Read more about refs in React https://reactjs.org/docs/refs-and-the-dom.html
I have an issue with getting the ref to the func in React components after I am wrapping it with injectIntl.
basically what I need is to get access to a func in the component by ref
here is what I am doing
class MainContainer extends React.Component {
constructor(props) {
super(props);
}
getSamples(){
return sth
}
render() {
return (<div>this.props.sth</div>)
}
export default injectIntl(MainContainer )
it possible to get the ref to the MainContainer after wrapped it with injectIntl?
The withRef option should be passed.
export default injectIntl(MainContainer,{ withRef: true })
The MainContainer wrapper component instance can be retrieved using
<MainContainer ref={c => { this.container = c; }} />
The wrapped component instance can be retrieved using
this.container.getWrappedInstance();
injectIntl has a forwardRef property which causes it to pass down ref to the wrapped component.
// MyComponent.jsx
// ...
export default injectIntl(MyComponent, {forwardRef: true});
// MyApp.js
import MyComponent from 'MyComponent';
class MyApp {
render() {
this.myComponentRef = React.createRef();
return <MyComponent ref={ref} />;
}
}
reference