I have a wrapper component similar to the following:
/* Some imports here */
class Wrapper extends React.Component {
renderChildren() {
const { children } = this.props;
return children.map(child =>
<Child key={child._id} />
);
}
render() {
return (
<div>
{this.renderChildren()}
</div>
);
}
}
Wrapper.propTypes = {
children: React.PropTypes.array,
}
export default createContainer(() => {
let children = [];
const subscriptions = [
Meteor.subscribe('Collection.all'),
/* ... */
];
if (subscriptions.every(sub => sub.ready()) {
/* Some irrelevant code here */
children = Collection.find({}).fetch();
}
return { children };
}, Wrapper);
And the Child component is similar to:
/* Some imports here */
class Child extends React.Component {
render () {
return (
<div></div>
);
}
}
export default createContainer(() => {
/* Some irrelevant code here that has to stay in createContainer (and not constructor)*/
}, Child);
I am attempting to write a test that, whenever a Document is inserted to the Collection, I compare if the length (amount) of Child components in Wrapper is incremented correctly. Before, when I did not need to use createContainer in my child element, the following:
it('should render with some children and reactively update with them', () => {
let children = [];
_.times(4, () => children.push(Factory.create('doc'));
const wrapper = mount(
<Wrapper />
);
chai.assert.notEqual(wrapper.find('Child').length, children.length);
wrapper.setProps({ children });
chai.assert.equal(wrapper.find('Child').length, children.length);
}
Did work as intended but as I added createContainer for the child element also the previously worked test(s) started to fail. It appears that enzyme's find('Child') function does not return any of these nodes anymore. Any suggestions are appreciated.
Related
I am calling a parent function from functional child component
but I am getting error props.onCall is not a function.
Also props come as undefined when I do console.log(props)
Here is the parent function :
class Parent {
construtor(props) {
super(props);
this.myFun = this.myFun.bind(this);
}
myFun = val = {
console.log(val);
}
render{
return (
<Child onCall={this.myFun} />
)
}
}
Here is the child function :
const Child = props => {
Handlefn = () => {
props.onCall("hi");
}
}
You have a ton of typos in your app.
Try this
Parent:
import React from "react";
import Child from "./Child";
export default class Parent extends React.Component {
constructor(props) {
super(props);
this.myFun = this.myFun.bind(this);
}
myFun = val => {
console.log(val);
};
render() {
return <Child onCall={this.myFun} />;
}
}
Child:
import React from "react";
const Child = props => {
const Handlefn = () => {
props.onCall("hi");
};
return <h1 onClick={Handlefn}>Hi</h1>;
};
export default Child;
For my website I want to include a feature that helps users randomly click a link programatically. The event happens in the parent component called StreamingPlaza, and its has a list of children components called StreamingCard, each containing a streaming link. Below is my code:
StreamingPlaza
class StreamingPlaza extends Component {
state = {
......
}
roomclicks = [];
componentDidMount() {
//Approach 1//
this.roomclicks[0].current.handleClick();
//Approach 2//
this.roomclicks[0].props.click = true;
......
}
setRef = (ref) => {
this.roomclicks.push(ref);
}
renderRoom = (room) => {
return <StreamingCard info={room} ref={this.setRef} click={false}></StreamingCard>;
}
render () {
const rooms = this.props.rooms;
return (
{ rooms && rooms.map (room => {
return this.renderRoom(room);
})
}
);
}
StreamingCard
class StreamingCard extends Component {
constructor(props){
super(props);
this.state = {
......
}
}
handleClick = () => {
document.getElementById("link").click();
}
render() {
return (
✔️ Streaming Link: <a id="link" href=......></a>
);
}
Regarding Approach 1, the console reported the error Cannot read property handClick of undefined. After I removed "current", it said that this.roomclicks[0].handleClick is not a function. Regarding Approach 2, I was not able to modify the props in this way, as the console reported that "click" is read-only.
Approach 1 is basically how its need to be done, but with React API.
See React.createRef
class StreamingPlaza extends Component {
roomclicks = React.createRef([]);
componentDidMount() {
// 0 is room.id
this.roomclicks.current[0].handleClick();
}
renderRoom = (room) => {
return (
<StreamingCard
info={room}
ref={(ref) => (this.roomclicks.current[room.id] = ref)}
click={false}
></StreamingCard>
);
};
render() {
const rooms = this.props.rooms;
return rooms.map((room) => {
return this.renderRoom(room);
});
}
}
i have two components: 1.Parent 2.Child
there is an event in child component called onChange() which return a value.
i want to receive the value which was returned from OnChange() in componentDidMount() in parent component.
Example:
class Parent extends PureComponent {
componentDidMount() {
let value = CHILD.onChange(); //triggered when ever onChange()
}
render(){
return(
<Child />
)
}
}
const Child = () => {
const onChange = () => {
const value = 1
return value;
};
}
class Parent extends PureComponent {
handleChildChange = value => {
//Do your stuff with value, pass it to the state and take it from there if you like
}
render(){
return(
<Child handleChange={this.handleChildChange} />
)
}
}
const Child = (props) => {
const onChange = () => {
value = 1
props.handleChange(value);
}
};
}
I have parent component with state which includes array of objects. I am passing this array to Child component as props. In child component array is sorted then map and as result returns grandchild component. It is working but from test case i received error "TypeError: Cannot read property 'sort' of undefined"
I am trying to check in child component if array exist and if array isn't undefined but i have the same error.
Parent component (airdropDB.airdrops is reference to array of objects from another file)
class ContentPanel extends Component {
constructor(props) {
super(props);
this.state = {
airdrops: airdropDB.airdrops
};
}
render() {
return (
<div>
<FiltrPanel />
<AirdropPanel airdrops={this.state.airdrops}/>
</div>
)
}
}
Child Component
class AirdropPanel extends Component {
render() {
let airdropBlocks = this.props.airdrops.sort((a, b) => {
return b.addDate - a.addDate;
}).map((e, i) => {
return (<Airdrop key={e.title + i}
title={e.title}
value={e.value}
status={e.status}
logo={e.logo} />)
});
return (
<div data-testid="airdropPanel">
{airdropBlocks}
</div>
);
};
};
Result is ok, i have proper and sorted airdropblocks but error from test case is alarming.
Test file:
import React from 'react';
import AirdropPanel from './AirdropPanel';
import { render } from 'react-testing-library';
describe('Airdrop Panel has', () => {
it('Airdrop block inside', () => {
const { getByText } = render(<AirdropPanel />);
expect(getByText(/rozpocznij/i)).toBeInTheDocument();
});
it('multi airdrop blocks inside', () => {
const { getByTestId } = render(<AirdropPanel />);
let moreThanOne = getByTestId("airdropPanel").childElementCount > 1;
expect(moreThanOne).toBe(true);
});
it('airdropBlock dates from newer to older sort function works', () => {
//Test zależny od bazy airdrop
const { getByTestId } = render(<AirdropPanel />);
const firstAirdropBLock = getByTestId("airdropPanel").firstChild;
expect(firstAirdropBLock.firstChild.textContent).toBe("Crypto Circle X");
});
});
.sort isn't run. That is most likely because this.props.airdrops is undefined
I don't know, but are you sure you shouldn't put something in your airdrops prop test?
const { getByText } = render(<AirdropPanel airdrops={??}/>);
I am trying to pass method from my parent component to child component. My code is correct i think but still it shows the error undefined is not an object(evaluating '_this2.props.updateData') . I don't know whats the issue because i searched the internet a lot and everyone is passing props to child like this. Kindly tell what am i missing
Parent:
class Parent extends React.Component {
updateData = (data) => {
console.log(`This data isn't parent data. It's ${data}.`)
// data should be 'child data' when the
// Test button in the child component is clicked
}
render() {
return (
<Child updateData={val => this.updateData(val)} />
);
}
Child:
class Child extends React.Component {
const passedData = 'child data'
handleClick = () => {
this.props.updateData(passedData);
}
render() {
return (
<button onClick={this.handleClick()}>Test</button>
);
}
}
`class Child extends React.Component {
handleClick = () => {
const passedData = 'child data'
this.props.updateData(passedData);
}
render() {
return (
<button onClick={this.handleClick}>Test</button>
);
}
}`
class Parent extends React.Component {
updateData = (data) => {
console.log(`This data isn't parent data. It's ${data}.`)
}
render() {
return (
<Child updateData={this.updateData} />
);
}
}
and child component: `
class Child extends React.Component {
const passedData = 'child data'
handleClick = () => {
this.props.updateData(passedData);
}
render() {
return (
<button onClick={this.handleClick}>Test</button>
);
}
}
`
You need to pass the function directly, not as a callback
class Parent extends React.Component {
updateData = (data) => {
console.log(`This data isn't parent data. It's ${data}.`)
// data should be 'child data' when the
// Test button in the child component is clicked
}
render() {
return (
<Child updateData={this.updateData} />
);
}
I think you need to pass a function like this. Check out this solution.