I'm making some modifications on this app by only understanding the syntax, i don't understand very much how it is built.
If someone could help me understand how the props get passed to this component that would be nice (i want to modify the props) React file .
The props are being passed at line 26
{childrenLinks.map((child, index) => {
return <DropDownChild child={child} key={`${child.url}-${index}`} />;
})}
childrenLink is also coming from a prop called linked passed from the parent component that calls SideMenuDropDown component.
I actually found it, it gets populated from the backend there is a file index.go in /pkg/api that does it
Related
As I read here, one way in reactjs to reuse code is to put it in a "container" component, then pass it down to its child via props. Cool.
Problems rise to me when, in my IDE (VSCode), I need to go to the method/property implementation: if code is imported via oldSchool "import", then everything works by "ctrl+clicking" the method name; but if I'm inspecting a method/property passed via props by the parent component, then "ctrl+click" on the method name is useless:
<div onClick={props.**methodFromParent**()}>Click me</div>
That's pretty obvuios, because there are no refs in my child code about the parent component itself (they get composited in another component ad-hoc). So is there a way to have this feature back? Because is very usefull to me.
Can't be possible.
If you define a method in the parent and pass it to the child you are not passing the mothod. What you actually are passing is a reference to a function and the child executes that function.
Like you mentioned it is possible to reuse code that way. The child doesn't know what method will be passed. It is not a static binding. So the IDE can't know either.
You could have something like:
// Parent component
const add = (a,b) => return a+b;
const sub = (a,b) => return a-b;
return ( <>
<child num=4 action={add}>
<child num=7 action={sub}>
</>);
// Child component
return (
<div>The result is {props.action(10, props.num)}</div>
);
As you see the property "action" doesn't relate to any particular method on the parent, it is just a property and the IDE can't show you a definition.
I need to test that a react component is called with opened={true} prop after an button click is fired. I am using testing-library ( testing-library/react + testing-library/jest-dom).
I mocked the Component using something like
import Component from "./path-to-file/component-name"
...
jest.mock("./path-to-file/component-name", () => {
return jest.fn().mockImplementation(() => {
return null
})
})
I first tried with:
expect(Component).toBeCalledWith(expect.objectContaining({"opened": true}))
expect(Component).toHaveBeenCalledWith(expect.objectContaining({"opened": true}))
expect(Component).toHaveBeenLastCalledWith(expect.objectContaining({"opened": true}))
but I got Error: expect(jest.fn()).toBeCalledWith(...expected).
Same went for expect.objectContaining({"opened": expect.anything()})
And even for expect(Component).toBeCalledWith(expect.anything())
And the difference is empty array:
I also tried with expect(ChartMenu.mock).toBeCalledWith(expect.anything()). I got a different error but still not working (this time the error was Error: expect(received).toBeCalledWith(...expected) + Matcher error: received value must be a mock or spy function)
Thank you in advice!
EDIT: here is a simplified version of the component I want to test:
const Component = () => {
const [chartMenuOpened, setChartMenuOpened] = useState(false)
return (
<Flex>
<EllipseIcon onClick={() => setChartMenuOpened(true)}>
+
</EllipseIcon>
<ChartMenu
opened={chartMenuOpened}
close={() => setChartMenuOpened(false)}
/>
</Flex>
)
}
Basically I want to make sure that when the + icon is clicked the menu will be opened (or called with open value). The issue is that I cannot render ChartMenu because it needs multiple props and redux state.
I was able in the end to mock useState in order to check that the setState was properly called from the icon component (in order to make sure there won't be future changes on the component that will break this using this post).
But I would still really appreciate an answer to the question: if there is any way to create a spy or something similar on a react component and check the props it was called with? Mostly because this was a rather simple example and I only have one state. But this might not always be the case. Or any good idea on how to properly test this kind if interaction would be really appeciated.
I think you are on the right track to test if the component has been called with that prop, it's probably the syntax issue in your code
I learn this trick from colleague and you can try to see if this helps fix your issue.
expect(Component).toHaveBeenCalledWith(
expect.objectContaining({
opened: true,
}),
expect.anything()
);
While the question on how to is answered, I did some extra research on this and it seems like in React components there is a second parameter refOrContext (so basically most of the time it's an empty object, but it can also be a ref or a context)
Despite pointing out the reason for the behavior, I also wanted to highlight that it is safer to use expect.anything() as the second argument (rather than just {} which would work only in most of the cases ):
More information about React second argument here
So this is some React Native code from a textbook that I'm going through, specifically it is from the render method of App.js. Of course the /* ...*/ would be filled in with actual code but it's irrelevant to my question.
<MeasureLayout>
{layout => (
<KeyboardState layout={layout}>
{keyboardInfo => /* … */}
</KeyboardState>
)}
</MeasureLayout>
What I don't understand is what is happening with {layout => (.... So I take it that layout is an arrow function that returns this keyboardState component. So how does layout then pass itself into keyboardState's layout prop at this part <KeyboardState layout={layout}>? And why would I want to do that exactly? This whole part here is really baffling me.
React components have props and children properties. The children property is usually a React node, but it can also be a function that returns a React node.
So how does layout then pass itself into keyboardState's layout prop at this part ?
The MeasureLayout component was created so that its children property was defined as a function instead of a React node.
And why would I want to do that exactly?
For dependency injection and as a pattern that allows for a more declarative style of programming with class-based components.
Some more in depth reading:
Topic: Functions as children
https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9
https://codedaily.io/tutorials/6/Using-Functions-as-Children-and-Render-Props-in-React-Components
See that {} inside render method is used for some javascript statements.
For eg.
<Text>
{personFirstNam +" " +personLastName}
</Text>
But now that in your code there is again JSX elements inside {}, it is used inside unnamed function.
i.e.
{layout => (
...// here you can use JSX element which will be returned into render method for UI.
)}
alternatively, if you want some operations there,
{layout =>{
let extractData = fromSomeWhere;
let calculatePosition = getPosition();
return (<KeyboardState layout={layout}>
{keyboardInfo => /* … */}
</KeyboardState>)
}}
All of these was to just do some JS statement executions/operations inside one JSX element.
The <MeasureLayout> is passing an argument to its children as a function. and to recieve it an arrow function is used.
so, basically the code of <MeasureLayout> will be,
function MesauseLayout(props){
//Do things
// layout = some result.
return <div>{props.children(layout)}</div>
}
So, in order to receive this the child will have to be inside a function that accepts this value. So, an arrow function is used to receive this value.
<MeasureLayout>
{layout => (
<KeyboardState layout={layout}>
{keyboardInfo => /* … */}
</KeyboardState>
)}
</MeasureLayout>
But in my opinion, using a Context/Provider with a hook will be a better option if that is possible. This is generally only used in extreme cases. There is also another option to use React.cloneElement and passing additional props. But there are tradeoffs if you have to choose between these two. Plus, There is a concept called render props which is commonly used in new libraries.
I have a strange case where I used code splitting within React SPA.
My code needs to render sometimes thin component, and in other cases a full component (for logged-in users).
now, Component has been sent to the class as part of props, and within render function I'm trying to render:
<this.props.Component />
and, here is the strange case. sometimes this line of code throws error:
error Cannot read property 'Component' of undefined
with stack trace that pointing to this line. In other cases it works perfectly.
Could anyone explain if this syntax is wrong? or maybe what causes it not to work sometimes?
Seems that the correct answer is that this syntax is not allowed (as of React 16),
I still can't understand why it had worked for me,
but if someone needs to render a component based on props he gets, he has to do it this way (thanks to #David):
{this.props && this.props.Component({
onClickHandler: this.onClick,
currentUser: this.props.currentUser,
etc..
})}
and type of Component must be a function.
another option to whom may want to write pure JSX:
const { Component } = this.props
return (
<Component
currentUser={this.props.currentUser}
onClickHandler={this.onClick />
)
I'm confused on the point of React.forwardRef. As explained in its documentation, I understand that its main use is for a Parent Component to gain access to DOM elements of the Child Component. But I can already do that without even having to use it.
Here is a code example that you can plug into CodeSandbox and see that it works:
import React, {useRef, useEffect} from "react";
import "./styles.css";
const ChildComponent = (props) => {
useEffect( ()=> {
props.callbackFunction()
})
return(
<div ref={props.fRef}>
{"hello"}
</div>
)
}
export default function App() {
const callbackFunction = () => {
console.log("The parent is now holding the forwarded ref to the child div: ")
console.log(forwardedRef)
}
const forwardedRef = useRef(null)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
</div>
);
}
Or here's the embed of this example. Honestly, I'm kind of new to this and I don't know exactly how embeds work and whether someone fiddling with the embed changes my original Sandbox or not, so I was hesitant to put it. But here it is.
Example Forwarding Ref
In the example, the parent App() component successfully passes a ref to the child which the child attaches to its rendered div. After it renders, it calls a callback function to the parent. The parent then does a console log where it proves that its forwarded ref now has a hold of the child's div. And this is all done without React.forwardRef.
So what then is the use for React.forwardRef?
You're absolutely right that you can do what you've described. The downside is that you're forced to expose an API (ie: the fRef prop) for it to work. Not a huge deal if you're a solo developer building an app, but it can be more problematic eg. if you're maintaining an open-source library with a public API.
In that case, consumers of the library won't have access to the internals of a component, meaning you'd have to expose it for them somehow. You could simply do what you're suggesting in your example and add a named prop. In fact, that's what libraries did before React 16.3. Not a huge deal, but you'd have to document it so people know how to use it. Ideally, you'd also want some kind of standard that everyone used so it wasn't confusing (many libraries used the innerRef naming convention), but there'd have to be some consensus around that. So all doable, but perhaps not the ideal solution.
Using forwardRef, passing a ref to a component just works as expected. The ref prop is already standardized in React, so you don't need to go look at docs to figure out how to pass the ref down or how it works. However, the approach you describe is totally fine and if it meets your needs, by all means go with that.
As mentioned in the docs , it's useful for highly reusable components, meaning components that tend to be used like regular HTML DOM elements.
This is useful for component libraries where you have lots of "leaf" components. You've probably used one like Material UI.
Example:
Let's say you're maintaining a component library.
You create a <Button/> and <Input/> component that maybe just adds some default styling.
Notice how these components literally are just like regular HTML DOM elements with extra steps.
If these components were made to be used like regular HTML DOM elements, then I expect all the props to be the same, including ref, no?
Wouldn't it be tedious if to get the button ref from your <Button/> component I'd have to get it through something like fRef or buttonRef ?
Same with your <Input/>, do I have to go to the documentation just to find out what ref to use and it's something like inputRef ? Now I have to memorize?
Getting the ref should be as simple as <Button ref={}/>
Problem
As you might know, ref will not get passed through props because, like key, it is handled differently by React.
Solution
React.forwardRef() solves this so I can use <Button ref={}/> or <Input ref={}/>.