How to fix - Functions are not valid as a React child? - javascript

I’m calling a function that returns some html code.
But if I want to send this function a parameter, then it tells me that Functions are not valid as a React child, the problem is that I want to access the props from the function, in order to do that, I changed the call in jsx as:
... ...
{this.showActivitiesIcon.bind(this)}
... ...
I tried setting a state inside the component, and setting the state from componentDidMount
componentDidMount = () => {
this.setState({
currentCountry: this.props.country
})
}
But, inside componentDidMount, there’s no such thing as this.props.country, and it’s useless to set this.componentDidMount.bind(this) inside the constructor. What can I do to fix it?

Here is the correct syntax, because bind(thisArg) returns a function:
{this.showActivitiesIcon.bind(this)()}

You seem like something:
super(props)
Can you share the whole code for this component?

Seems like you're are not calling the function in your JSX.
Make sure you invoke it while using it so that it returns valid JSX.
this.showActivitiesIcon.bind(this)()

Related

How to call a method from child component to parent one?

I have a child component called ZimModel.vue where I created a method drawGrid(). I need to call this method in parent component (mainPage.vue). The idea is to call this method once the user has finished typing values in input (namely: width of the grid - I added #input event to v-model="inputWidth"). That's why I also use setTimeout with 5 sec delay. However, I have no idea how to 'send' this method up to parent component. I tried with emit but I don't think it makes any sense.
I use Vuex store in my app but this particular method is strictly related to other data and methods in ZimModel.vue so I don't think it' makes sense to move it to Vuex. Is there any pattern/good practice I should follow in this case?
Here is a reproducible example: https://codesandbox.io/s/vue-2-playground-vuex-drag-and-snap-to-tiles-un6984?file=/src/components/mainPage.vue.
As an example I added myGreeting() method (in mainPage.vue) to show how I want my program to work. I need to replace this exemplary method with target drawGrid() method.
Using $ref will solve your issue:
<ZimModel ref="zimModel" />
And inside your method:
triggerDrawing() {
clearTimeout(this.timer);
// this.timer = setTimeout(this.myGreeting, 5000);
this.$refs.zimModel.drawGrid();
}
Whilst the using ref should work, you should consider outsourcing the method to a .js and importing the method in the files you need it. This is especially recommended when using a method in several components.
In the new file:
export function drawGrid() {
// Your code
}
In your components
</template>
<script>
import { drawGrid } from 'relativePath'
// using {} you can import a single function or few select to improve effectiveness
...
Then you can just call the function.

Is calling functions and creating new variables in react component body bad?

I've been working with react for years and I still have a simple question that I could never understand nor get the answer anywhere. Is calling an outside function in react component body bad?
For example:
import { getUser } from './helpers';
function MyComponent() {
const user = getUser();
return (
...
What will happen to user variable when component gets re-rendered by the parent component? Variables created in component body are created again in memory? Should I use useCallback or useMemo? I feel those two react functions are for other reasons, as expensive calculations and to prevent unecessary prop re-render.
To answer your first question in my experience I've never heard of calling outside functions within a react body as bad. In fact it's always been something that was encouraged especially for helper functions like in your example. There are definitely other ways to handle helper functions that may be needed multiple times (useContext comes to mind) but I don't see anything wrong with importing an outside function to call within a react body.
As far as what happens to user in your example it would get reset to the new return of getUser() upon any component re-render.
The user variable will be set to the value returned by getUser() on each re-render. And yet, getUser() will run on each re-render.
React Hooks are functions with use at the beginning of the function name, documented here.

Thus returning a JSX necessarily makes the function a component?

I have simple code, I have a component called Feed with some props.
On the main content component called Articles I map through a js object and return Feed component
Now, everyone are using an anonymous function to do so.
<div>
{data.map(()=> <Feed/>))} (sorry if the syntax a bit wrong but you get the idea
</div>
now, I took the function that returns Feed outside the map function
function createFeed (feedData) {
return <Feed props/>
}
and put it
<div>
{data.map(createFeed)}
</div>
and it workds wonder, but, thus createFeed is also a component (so I need to change the name to CreateFeed) or is this just a function that return an object to a new array created by the map function thus it's only a function and not a component?
There's no magic here.
<div>{data.map(createFeed)}</div>
Is equivalent to:
<div>{ data.map(item => createFeed(item) }</div>
Since the createFeed function returns the component without adding any logic, you can just omit it and return the component. It's all the same.
Edit:
In your case, you're merely using the function as a factory, not as a functional component, so you could argue that it doesn't need to be capitalized.
That is, if you're sure that you won't use the function as a component in Jsx, this is not a problem. If you want to use it as Jsx, this causes a problem, which is documented here: https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized
If there is no use in having a factory function, I would omit it, but in the end choice is up to you.

React.js: Passing props to props?

I am learning React via an online course and have stumbled across a situation where a property is attached to another property like so:
this.props.property01(this.props.property02)
Seeing as the tutor only briefly addresses this line of code I cannot but remain baffled as to what this "concatenation" syntax actually stands for, i.e. what it causes behind the scenes. Coming from Vanilla JS it looks like property02 is being used as an argument for property01 but that seems too simple an answer. That being said, I understand the remaining code quite well.
To provide some context I have created this codepen in which the problem I refer to above is given by this.props.onDelete(this.props.whichItem);.
Seeing as I could not find any related questions, I would be grateful for some insightful elaboration on this one.
The properties of a React component can be functions. When I see:
this.props.property01(this.props.property02)
I think that:
this.props.property01 is a function.
this.props.property02 is passed to the function as an argument.
This means that the component would be used as:
<SomeComponent property01={(a) => { /* so something with "a" ... */ } property02={"someValue"} />
If property02 is only used to be passed to property01 and nothing else I would prefer something like:
<SomeComponent property01={(a) => { /* do something with "someValue" ... */ } />
Which means that there is no need for a property called poperty02.
Coming from Vanilla JS it looks like property02 is being used as an argument for property01
That's it, you are correct.
this.props.property01(this.props.property02)
property01 is a method, property02, the argument.
A more elaborated explanation for anyone else looking at this:
Assume this line is in a component called MyComponent and property01 is a prop in MyComponent.
The parent component's render() method, would contain something like this:
<MyComponent property01={this.someMethod.bind(this)} />
Where someMethod belongs to that parent component but it becomes available as property01 in MyComponent (the child component).
If you can understand the basic react code this question will help you because in that code I passed props and state from parent component to the child component. You can play with it try to do whatever you want.
How to pass state from parent compont to child component in route (react-route-dom) reactjs

this.refs.something returns "undefined"

I have an element with a ref that is defined and ends up getting rendered into the page :
<div ref="russian" ...>
...
</div>
I want to access the DOM element properties like offset... or something. However, I keep getting undefined and I haven't the faintest idea why. After some searching it's clear that refs are only applicable to one file but I'm not using this anywhere besides this one page. I'm saying this to log it:
console.log('REFS', this.refs.russian);
What could be causing this?
Check that you are not accessing ref before the child component has been mounted. E.g. it doesn't work in componentWillMount. A different pattern which auto invokes ref related callback after the element has been mounted is this-
<div ref={(elem)=>(console.log(elem))}/>
You can use this notation to get mounted elements in deep nesting as well -
<div ref={this.props.onMounted}/>
The correct place to work with refs is inside specific React lifecycle methods e.g. ComponentDidMount, ComponentDidUpdate
You cannot reference refs from the render() method. Read more about the cautions of working with refs here.
If you move your console.log('REFS', this.refs.russian); call to ComponentDidMount or ComponentDidUpdate lifecycle methods (assuming you are on React >= 14) you should not get undefined as a result.
UPDATE: also refs will not work on stateless components per the caution link above
Update since React version 16.4
In your constructor method define your ref like this
constructor(props) {
super(props);
this.russian = React.createRef();
}
In your render where you are using ref do this.
<input
name="russian"
ref={this.russian} // Proper way to assign ref in react ver 16.4
/>
For e.g if you want to have focus when component mounts do this
componentDidMount() {
console.log(this.russian);
this.russian.current.focus();
}
Reference Refs Documentation React
I was having a similar issue in my form validation methods, trying to assign this.ref.current.reportValidity()
Writing the method I was doing this in as validate = () => {} instead of validate() {} helped me out, but I'm not totally sure why exactly, just something I remembered from habits I had in my past work experience that gave me this. Hope it helps and could someone kindly clarify this answer with why this might work exactly.
If you are exporting class withStyle, please remove and export default nomally.
Instead of putting your Console.log inside the function example(){...} you should put it inside:
example=()=>{....}

Categories