Render body from function react - reactjs

I have the following React class
class Cards extends React.Component {
//state
//axios-> set new state
render(){
const{t} = this.props;
return(
// something
<RenderCards t={t}/>
)};
}
And my RenderCards:
let RenderCards = (props) => {
const {t} = props;
// do something with t
}
The thing is that I also want to pass the state with the props but the following approach is not working :
<RenderCards t={t} st={st}/> //st is this.state
let RenderCars = (props,st) =>{
const {st} = st; // -->is undefined!
}
How should I properly pass the state? Thank you!

All of the things that you pass as JSX attributes will go into the props argument of your stateless component; it doesn't matter where they came from originally. So the signature of RenderCards will always be props => JSX.Element:
let RenderCards = (props) => {
const { t, st } = props;
// do something with t and st
};
Personally I would remove the definition of RenderCards outside of the parent component as well, to avoid unnecessarily redefining it every time the parent is rendered.

Here <RenderCards t={t} st={st}/> the state is passed as a prop. It won't be available as second function parameter (which is now deprecated context):
let RenderCards = (props, st) =>{...}
It is:
let RenderCards = (props) =>{
const {st} = props;
...
}

Related

Passing object to child component loses its properties and methods

I have App.js that has a component in it where I pass down props:
let chess = new Chess();
// lots of code...
console.log("chess in App.js", chess);
return <ChildComponent chess={chess} />;
The ChildComponent.js receives this prop as follows:
const ChildComponent = (chess) => {
console.log("chess", chess);
};
When I inspect that in Chrome, I get this:
So, I am somehow losing the object detail when I pass it down as props. Is there something obvious that I am doing wrong?
It needs to be in a {} because it's inside a props object
const ChildComponent = ({ chess }) => {
console.log("chess", chess);
};
OR
const ChildComponent = (props) => {
console.log("chess", props.chess);
};
Your code, log the props object,
try this
const ChildComponent = (props) => {
console.log('chess', props.chess)
}
or
const ChildComponent = ({chess}) => {
console.log('chess', chess)
}

React child component does not re-render when props passed in from parent changes

I have a simplified react structure as below where I expect MyGrandChildComponent to re-render based on changes to the 'list' property of MyParentComponent. I can see the list take new value in MyParentComponent and MyChildComponent. However, it doesnt even hit the return function of MyGrandChildComponent. Am i missing something here?
const MyGrandChildComponent = (props) => {
return (
<div>props.list.listName</div>
);
};
const MyChildComponent = (props) => {
return (
<div><MyGrandChildComponent list={props.list}/></div>
);
}
const MyParentComponent = (props) => {
const list = { listName: 'MyList' };
return (
<div><MyChildComponent list={list} /></div>
);
}
In your MyParentComponent, the list is not a state variable and as such changing it will not even cause a re-render. If you absolutely want that when ever you change the value of list it re renders, then you will want to bring state to your functional component and the way to do that is to use hooks.
In this case your parent component will be something like below
import React, {useState} from 'react'
const MyParentComponent = (props) => {
const [list, setList] = useState({ listName: 'MyList' });
return (
<div><MyChildComponent list={list} /></div>
);
}
then at the child component you render it as I suggested in the comment above.
The parent needs to hold the list as a state variable and not just as a local variable. This is because react rerenders based on a state or prop change and at the parent you can only hold it in the state. With this when the value of list changes there will be a re-render which will then propergate the change to the children and grandchildren.
Also the only way of maintaining state in a functional component is to use hooks.
const MyGrandChildComponent = (props) => {
return (
<div>{props.list.listName}</div>
);
};
You forgot the {} around props.list.listName

Attach a property to a functional component wrapped with React.forwardRef

I have a component wrapped with React.forwardRef and it so happens that it is a compound component as well.
I'm not sure how do I maintain
Form.Item = FormItem;
while the Form component function being wrapped with forwardRef.
const Form = React.forwardRef((props, ref) => { return <form></form>});
Typescript gives me an error (rigthly) saying
Property 'Item' does not exist on type 'ForwardRefExoticComponent>'.ts(2339)
Just to make it more clear of the solution, as it's on an external site (Credits to original author here, and thank you #Antoan Elenkov)
export interface Props = {
...yourPropsHere;
};
export interface CompoundedComponent extends React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLInputElement>> {
yourStaticFunctionOrSomethingLikeThat: () => void;
}
const Component = React.forwardRef<HTMLInputElement, Props>((props, ref) => (
<input ref={ref} {...props} />
)) as CompoundedComponent;
Component.yourStaticFunctionOrSomethingLikeThat = () => {};
This solution from the same GH thread seems nicer to me:
const Form = React.forwardRef(function Form(...) {
...
})
const FormItem = React.forwardRef(...)
const FormNamespace = Object.assign(Form, {Item: FormItem})
export {FormNamespace as Form}

Trigger Child component method when prop changes

I'm trying to make a child functional component to update when a Parent component changes a value in its state that I'm passing to a this child component as a prop.
The child component "receives" the value correctly and displays the prop value, but the method does not run again.
Child component
import React from 'react'
const MyCustomTable = props => {
const {
data = [],
} = props
const finalData = getSalesData() //This is the method i want to run when the selectedMonth prop updates
const getSalesData = () => {
//It does some calculations with the prop called data
}
return (
<Box>
{JSON.stringify(props.selectedMonth.value)}
<Table
data={finalData}
/>
</Box>
)
}
SalesByFamilyBU.propTypes = {}
export default MyCustomTable
The JSON.stringify line displays the changes correctly but I guess the getSalesData() is not automatically executed.
While you could use some lifecycle method or the useEffect hook to achieve what you want to do, I would rather use a functional approach.
In your example, finalData is a derived value of props.data and props.selectedMonth. You could then compute finalData directly from these props:
const MyCustomTable = props => {
const {
data = [],
} = props;
const filterData = (data, selectedMonth) => data.map(dataPoint => ({
...dataPoint,
selected: dataPoint.month === selectedMonth,
}); // or whatever, use your function logic here
const finalData = filterData(data, props.selectedMonth.value);
return (...);
};
If you really needed to call a function each time data is changing (ex. to fetch data elsewhere) you could use something like that:
const MyComponent = ({ data }) => {
const [finalData, setFinalData] = useState([]);
const myFunction = () => {
const newData = ... // whatever you need to do
setFinalData(newData);
};
useEffect(myFunction, [data]);
return ...;
};

How to initialize the react functional component state from props

I'm using React hooks for app state, I wondered about how to initialize the functional component state using props? The useState hook doc says something definitive like,
const [count, setCount] = useState(0);
I want to initialize that 0 value by the value of props being passed to the component. The Older as,
import React from 'react';
export default class Sym extends React.Component{
constructor(props){
super(props);
this.state = {
sym : [0,3,2,8,5,4,1,6],
active: this.props.activeSym
}
this.setActive = this.setActive.bind(this);
}
setActive(itemIndex){
this.setState({
active: itemIndex
});
}
render(){
return (
<div><h1>{ this.state.sym[this.state.active]}</h1></div>
);
}
}
works fine. Where the parent Component passes activeSym prop and Sym component initializes the state with it using this.props.activeSym in constructor. Is there any workaround to achieve same in function component?
First you can define it from props (if the prop exist):
const [count, setCount] = useState(activeSym);
And then you can update this value, when prop doesn't have a value immediately (when component rendered):
useEffect(() => {
if (activeSym) {
setCount(activeSym);
}
}, [activeSym])
Yes, this can be possible with functional component too! You just need to add useEffect to listen to prop change for initializing state with prop value
export const newComponent = (props) => {
const { path, value, info, update } = props;
const [val, setVal] = useState(value);
useEffect(() => {
setVal(value);
}, [value]);
return <div>{val}</div>;
};
Attching sandbox link
https://codesandbox.io/s/confident-agnesi-ohkq7?file=/src/MakeComponent.js
Yes you can first define state using props:
const [name, setName] = useState(props.obj?.name);
And then you can if the state is still undefined means props doesn't have a value, then:
useEffect(() => {
if (JSON.stringify(props.obj) !== "{}") {
setName(props.obj?.name);
}
}, [props.obj])
Just as follows :
const MyFunctionalComponent = ({myProp}) => {
const [count, setCount] = useState(myProp)
return (
/* ... */
)
}
There are two ways you can change the state:
one is using this.state and
another one is this.setState.
We use the first method to initialize the state in the constructor, and the second method is used for the rest of the time.
Initialize State in the Constructor
One way is to initialize the state is in the constructor. As we discussed earlier constructor is the first method to be called when React instantiates the class. This is the perfect place to initialize the state for the component because the constructor is called before the React renders the component in the UI.
class WithConstructor {
constructor() {
this.state = {
name: "StackOverflow"
}
}
}
Initialize State Without Constructor
Another way of initializing state in React is to use the Class property. Once the class is instantiated in the memory all the properties of the class are created so that we can read these properties in the render function.
class WithoutConstructor {
state = {
name: "StackOverflow"
}
}

Resources