I have a React component that looks like this
'use strict';
import 'babel-polyfill';
import React from 'react';
import TreeNode from './TreeView';
export default React.createClass({
mapFromApi : function(data) {
const rec = (tree) => tree.reduce((x,y) => {
const newObj = {
"id" : y["#id"],
"name" : y["rdfs:label"]
};
if (y.hasOwnProperty("options")) {
newObj.children = rec(y.options, []);
}
if (y.hasOwnProperty("children")) {
newObj.children = rec(y.children, []);
}
x.push(newObj);
return x;
}, []);
let t = rec(data);
return t;
},
render: function (data) {
let tree1 = this.mapFromApi(this.props.data.properties).map(child => {
return <TreeNode key={child['id']} data={child}/>;
}.bind(this));
return (
<div className='vocab'>
<h4>vocab1</h4>
<div className='accordion'>
{tree1}
</div>
</div>
);
}
});
When I run this I get an error on the bind keyword
SyntaxError: App.jsx: Unexpected token, expected , (56:5)
54 | let tree1 = this.mapFromApi(this.props.data.properties).map(child => {
55 | return <TreeNode key={child['id']} data={child}/>;
> 56 | }.bind(this));
| ^
57 |
58 | return (
59 | <div className='vocab'>
I'm not sure if this has to do with my Babel setup and I'm very confused about the whole es version situation.
Can some one help me resolve this? Many thanks.
If you simplify the way this code is laid out, these kind of syntax errors should be easier to identify.
let { data } = this.props;
this
.mapFromApi(data.properties)
.map(child => <TreeNode key={child.id} data={child} />)
The arrow function is already going to .bind(this) for you, so you can just omit that.
You shouldn't need to use .bind(this) because you are using the ES6 arrow function => and that will reference the correct this
I would write some thing like this
const {data} = this.props;
let tree1 = this.mapFromApi(data.properties).map(child => {
return <TreeNode key={child['id']} data={child}/>;
});
Related
my props in the children class is supposed to be an array of Event objects.
I am checking beforehand, if the array is empty in App.js like this:
function App() {
class Event {
constructor(id, title, date){
this.id = id;
this.title = title;
this.date = date;
}
}
const [events, setEvents] = useState([])
const [ids, setIds] = useState([])
const [safedIds, setSafedIds] = ([])
const [eventsPrep, setEventsPrep] = useState([Event])
useEffect(() => {
fetch('https://someAPI.com')
.then(response => response.json())
.then(
res => {setEvents(res);
console.log(res);
})
.catch(err => console.log(err))
.then(handleIncomingData())
//.then(console.log("was here"))
}, [])
function handleIncomingData () {
if(events.length > 0) {
events.forEach(event => {
ids.push(event["_id"]);
let date = new Date(event["date"]);
eventsPrep.push(new Event(event["_id"], event["title"], date.toDateString()))
})
}
}
return (
<>
<Navbar/>
{eventsPrep.length > 0 ? <Home events={eventsPrep}/> : <></>}
</>
);
}
export default App;
but whenever I try to reach the props in the child component it is considered undefined.
My child component:
import React from 'react'
import SingleEvent from '../../event/SingleEvent'
export const Home = (props) => {
console.log(props.events)
return (
<>
{props?.events
? props.events.forEach((event) => {
console.log('was here 2');
return <SingleEvent title={event.title} start={event.date} />;
})
: 'no upcomming events'}
</>
);
}
Even if I only pass a string down, it is still undefined.
Thanks for help!
In your useEffect() you update events via setEvents(res) and call handleIncomingData() after that.
In handleIncomingData() you use events, but it will still hold the value from previous render / from the initialization as setEvents(res) will not change events immidiately. You can console.log(events) inside that function to investigate this.
Instead you can pass res into handleIncomingData() and use it instead of events inside that function. So in you useEffect you would have:
.then(response => response.json())
.then(
res => {
setEvents(res);
handleIncomingData(res);
})
In addition in handleIncomingData() use setEventsPrep(...) instead of eventsPrep.push(), as mentioned in the comment.
You are returning 2 return statments in the component.
Only need to return 1 return statement in component
export const Home = (props) => {
return (
<>
{props?.events && Object.values(props.events).length > 0
? props.events.forEach((event) => {
console.log('was here 2');
return <SingleEvent title={event.title} start={event.date} />;
})
: 'no upcomming events'}
</>
);
};
Also to check whether eventsPrep has a length > 0 then try it this way if eventsPrep is an object
eventsPrep && Object.values(eventsPrep).length > 0
FYI: I am using ES6 on ReactJS
I have a switcher. I need it to switch to the other side when clicked.
If click on the side that is currently active does nothing.
Here is my sample code
import { useState } from 'react'
const {isLeftButton, setIsLeftButton} = useState(true);
const toggleSwitcher = () => {
setIsLeftButton(!isLeftButton)
}
const home = () => {
...
return (
<CustomSwitcher isLeftButton={isLeftButton} toggleSwitcher={toggleSwitcher} />
)
...
}
export default Home
Here is the code inside the CustomSwitcher
const CustomSwitcher = (isLeftButton, toggleSwitcher) => {
const leftButton = () => {
if (isLeftButton !== true) {
toggleSwitcher()
}
}
const rightButton = (isLeftButton, toggleSwitcher) => {
if (isRightButton === true) {
toggleSwitcher()
}
}
return (
<div>
<CustomButton onClick={LeftButton}>Left Button</CustomButton>
<CustomButton onClick={rightButton }>Right Button</CustomButton>
</div>
)
}
export default CustomSwitcher
However I got this error
TypeError: toggleSwitcheris not a function
12 | const CustomSwitcher = () => {
13 |
14 | if (leftButton !== true) {
> 15 | toggleSwitcher()
| ^ 16 | }
17 | }
18 |
As I understand, when passing a function down to a component. The function is no longer a function.
And I don't think my code is good. If you can think of a better way to do so. Please contribute.
You are not using the correct way to access the props.
Try to replace
const CustomSwitcher = (isLeftButton, toggleSwitcher) => {
with
const CustomSwitcher = ({isLeftButton, toggleSwitcher}) => {
const CustomSwitcher = (isLeftButton, toggleSwitcher) => { ... }
is not the correct way to build a component.
Either use the props object
const CustomSwitcher = (props) => {
// props.toggleSwitcher
}
Or destructure props
cost CustomSwitcher = ({isLeftButton, toggleSwitcher}) => { ... }
You need to use useState inside a functional component. In your case, inside home. Hooks cannot be used at the global level.
Consequently, you need to define toggleSwitcher inside home also.
I am trying to create a unit test that will test a component's method to run if a certain <a> tag is selected within it. For some reason I am so close but cannot get it to work. I am able to run that method just fine since the console.log within it fires off during the test, but how do I make it take a step back and just simply test for if the function firies off instead of actually firing it off.
Here is the component I am testing on, Breadcrumbs.tsx:
import React, { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom';
import Constants from '../../../../../core/constants';
import { BreadcrumbsProps } from './BreadcrumbsProps';
import { AgentsMode } from './AgentsProps';
const Breadcrumbs = (props: BreadcrumbsProps): ReactElement => {
const { agentsMode } = props;
const { t } = useTranslation(Constants.Localization.Namespaces.RECRUIT);
const history = useHistory();
const savedSearchesHandler = (): void => {
console.log('this ran');
const savedSearches =
`${Constants.Routes.Recruit.MODULE}${Constants.Routes.Recruit.SAVED_SEARCHES}`;
history.push(savedSearches);
};
const mlsSearchHandler = (): void => {
const mlsSearch =
`${Constants.Routes.Recruit.MODULE}${Constants.Routes.Recruit.MLS_SEARCH_START}`;
history.push(mlsSearch);
};
return (
<>
<div className="my-favorites-layout-hack d-flex align-items-center align-content-center">
<div>
<nav
className="mr-2 breadcrumbs-mb-0" aria-label="breadcrumb" id={'breadcrumb'}>
<ul className="breadcrumb mb-0"><li><i
className="material-icons mr-2" id="home-icon" aria-hidden="true">home</i></li>
<li
className="breadcrumb-item-saved"
id={'saved-searches-link'}><a onClick={savedSearchesHandler}
href="#">{t('labels.savedSearches')}</a></li>
<li
className="breadcrumb-item">
{agentsMode != AgentsMode.mlsSearchStart ? (<a href="#" onClick={mlsSearchHandler}>
{t('labels.mlsSearch')}</a>) :
(t('labels.mlsSearch'))}
</li>
{agentsMode != AgentsMode.mlsSearchStart ? <li
className="breadcrumb-item">
{t('labels.unsavedSearch')}
</li> : null}
</ul>
</nav>
</div>
</div>
</>
);
};
export default Breadcrumbs;
and here is my unit test (let me know if I need to provide more information):
this.when.push({
beforeEachRender: () => {
this.clientId = '037COL';
this.user = userWithFullPermissions;
document.cookie = `token=${testCookie}; expires=Thu, 01 Jan 2070 00:00:00 UTC; path=/;`;
count++;
// const unsavedSearchDetails = agentSearchTestDetails;
// unsavedSearchDetails.criteria.searchId = UNSAVED_SEARCH_ID;
// window.history.replaceState({ state: { agentSearchDetails: unsavedSearchDetails } }, 'Mock');
if (count === 1) {
this.mockHttpRequests();
} else {
this.mockHttpRequestsReversed();
}
},
describe: 'When the search results page is reached and the saved search route is clicked',
then: async () => {
test('Then the Saved Searches page should render', async () => {
const history = createMemoryHistory();
history.push('/');
const savedSearchesHandler = jest.fn();
const baseProps = {
savedSearchesHandler
};
const wrapper = shallow(<Breadcrumbs {...baseProps} agentsMode={AgentsMode.algorithmSearch} />);
wrapper.find('a').at(0).simulate('click');
expect(baseProps.savedSearchesHandler).toHaveBeenCalled();
});
},
});
Unfortunately I am left with this error message:
TypeError: Cannot read property 'push' of undefined
15 | const savedSearches =
16 | `${Constants.Routes.Recruit.MODULE}${Constants.Routes.Recruit.SAVED_SEARCHES}`;
> 17 | history.push(savedSearches);
| ^
18 | };
19 |
20 | const mlsSearchHandler = (): void => {
I've sifted through a number of StackOverflow posts and still have been coming up short on this history dilemma. Any advice is appreciated!
Summary
I have the following function inside of a functional component which keeps coming back undefined. All of the data inside the function, tableData and subtractedStats are defined and accurate.
This is probably just a small JavaScript I'm making so your help would be greatly appreciated!
Code
This is a functional component below:
const TableComponent = ({ tableData }) => {
formatTableData = () => {
console.log("inside sumDataFormat", tableData);
return tableData.forEach(competitor => {
let subtractedStats = [];
console.log("competitor in", competitor);
for (const i in competitor.startingLifeTimeStats) {
if (competitor.startingLifeTimeStats[i]) {
competitor.stats
? (subtractedStats[i] =
competitor.stats[i] - competitor.startingLifeTimeStats[i])
: (subtractedStats[i] = 0);
}
}
console.log("subtractedStats", subtractedStats);
return subtractedStats;
});
};
useEffect(() => {
console.log("formatTableData", formatTableData());
});
}
Edit:
Can someone help me to what's wrong in this code (how to solve this?) and could briefly explain a functional component
The forEach function doesn't not return anything, it simply iterates over your array, giving you an undefined, the map function could be what you were looking for :
formatTableData = () => {
console.log("inside sumDataFormat", tableData);
return tableData.map(competitor => { // This returns another array where every element is converted by what's returned in the predicate
Functional Component are the most basic kind of React component, defined by the component's (unchanging) props.
Functional Component needs return some JSX code (UI) (can be null too).
Here's an example of most basic Functional Component
const App = () => {
const greeting = 'Hello Function Component!';
return <Headline value={greeting} />;
};
const Headline = ({ value }) => {
return <h1>{value}</h1>;
};
export default App;
Solution Code
Here's the solution of the above example as a Functional Component
This is solution below uses hooks to save data to component's state and also uses lifecycle methods to parse that data on componentDidMount:
const TableComponent = (props: ) => {
const [state, setState] = useState(initialState)
// componentDidUpdate
useEffect(() => {
setState(getData(props.data));
}, []);
// getData() - Parser for data coming inside the functional Component
const getData = (tableData) => {
return tableData.map(competitor => {
return competitor.startingLifeTimeStats.map((item, index) => {
return item && competitor.stats ? competitor.stats[index]-item : 0;
})
})
};
// UI (JSX)
return (
<Text>{JSON.stringify(state)}</Text>
);
}
export default TableComponent;
Try with map sample code as below.
render() {
return (<div>
{this.state.people.map((person, index) => (
<p>Hello, {person.name} from {person.country}!</p>
))}
</div>);
}
I get the below error when I run "next export". My build is fine but the export fails. I have been following a lot of tutorials but couldn't find a solution. Have I defined my someEntryAsProp correctly?
import Layout from '../components/myLayout.js'
import Link from 'next/link'
import {createClient} from '../helpers/getcontent';
import { type } from 'os';
function getPosts(){
return [
{ id:'hello-nextjs' , title:'Hello Next.js' },
{ id:'learn-nextjs' , title:'Learn Next.js is awesome' },
{ id:'deploy-nextjs' , title:'Deploy apps with Zeit' },
]
}
const PostLink = ({ post }) => (
<li>
<Link as={`/p/${post.id}`} href={`/post?title=${post.title}`}>
<a>{post.title}</a>
</Link>
</li>
)
const Index = () => (
<Layout>
<h1>My Blog</h1>
<p>{someEntryAsProp.fields.title}</p>
<ul>
{ getPosts().map((post) => (
<PostLink key={post.id} post={post}/>
))}
</ul>
</Layout>
);
Index.getInitialProps = async () => {
console.log('> Starting import',);
const client = createClient();
const entries = await client.getEntries({
// some query
content_type:type,
include:2
})
console.log(entries.items[0])
console.log('> Content gotten and written for',)
return { someEntryAsProp: entries.items[0] };
//return {};
};
export default Index
Error:
TypeError: Cannot read property 'someEntryAsProp' of undefined
Can anyone please help me where I am doing wrong?
You need to pass the props to your page-component as an argument:
const Index = ({someEntryAsProp}) => (...)