How to use react-sortable-hoc - reactjs

I am trying to use the component "react-sortable-how". I wrote this:
<SortableContainer>
{ questions.map((question,index) => (
<SortableElement key={index}>
<QuestionForm key={index} question={question} mode="update" betId={this.props.match.params.betId} cb={this.getQuestions} />
</SortableElement>
)) }
</SortableContainer>
But I have this error :
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
I am a beginner in React. I don't understand what this message mean. I tried a lot of things without success.

Related

Why can't a Higher Order Component (HOC) directly return it's component argument?

I'm learning about Higher Order Components in React and I encountered some code that is very confusing to me.
function HOCFunction(Component){
function handleComponent(){
return (<Component/>);
}
return handleComponent;
}
^^^ This code will work and run normally. The HOC function takes a Component as a parameter, creates a functional component, and then returns it.
So here is my question...
function HOCFunction(Component){
return (<Component/>)
}
^^^ This code throws an error "Warning: React.jsx: type is invalid..." I would expect this code to work as well. Why can't I directly return the component passed in as it's argument?
Is there something about JSX that I don't understand?
Edit - Here's how I'm using the HOC.. I'm using react native btw
const TextComponent = HOCFunction(() => {
return <Text>this is text from a hoc</Text>
}
And then 'TextComponent' could be rendered like so..
function ParentComponent(){
return( <TextComponent/> )
}
I would have expected to be able to return the component parameter directly, but in order for the code to run, it seems like I have to create a separate component inside the HOC function. Why is that?

react.js TypeError: lights.map is not a function

So i am trying to map the data i get from this api, but it gives an error saying "TypeError: lights.map is not a function"
Here is the function which is called to make the call from the API:
function getLight(){
Axios.get('http://{IP}/api/{KEY}/lights').then((res) =>{
console.log(res.data)
setLights(res.data)
})
}
And here is my map:
<button onClick={getLight}>Lights 1</button>
<div>
{lights.map((light) =>{
return(
<li>{light.name}</li>
)
})}
</div>
You should be sure that lights will always be an array so you can use map function.
If you are not sure that lights will be an array you can use
<>
{lights?.map && lights.map((something)=><div>{something}</div>)}
</>
Or, if you do not have access to modern syntax
<>
{lights && lights.map && lights.map((something)=><div>{something}</div>)}
</>
So you will check if map function really exists in lights object(or it's prototype) prior to using it and if not - return undefined and React will not render that line of jsx (you can render some kind of loader animation while you not have an array, for example)
BUT I don't think it's good solution - you really need to check when your variable gets non-array value which cause an error.

How can I get the JSX elements rendered by a component?

Short version: I have a component type (a class or a function) and props for it. I need to "render" the component to obtain its representation in JSX elements.
(I use the quotes because I mean «render into JSX elements» not «render into UI» and I am not sure about the terminology.)
Example:
const Foo = (props) => <div><Bar>{props.x + props.y}</Bar></div>;
// is an equivalent of `const elements = <div><Bar>3</Bar></div>;`
const elements = render2elements(Foo, { x: 1, y: 2 });
function render2elements(type, props) {
/* what should be here? */
}
Long version (for background story enthusiasts, may be skipped imo)
I have a React code whose very simplified version looks like this:
function Baby(props) {
/* In fact, it does not even matter what the component renders. */
/* It is used primarily as a configuration carrier. */
}
function Mother({ children }) {
const babies = getAllBabies(React.Children.toArray(children));
const data = parseData(babies);
return buildView(data);
}
function SomeOtherComponent(props) {
const { someProps1, someProps2,
someProps3, someCondition } = someLogic(props);
return (
<Mother>
<Baby {...someProps1} />
<Baby {...someProps2} />
{someCondition ? <Baby {...someProps3} /> : null}
</Mother>
);
}
It may be strange but it works. :) Until someone wants to do a little refactoring:
function Stepmother(props) {
const { someProps1, someProps2,
someProps3, someCondition } = someLogic(props);
return (
<>
<Baby {...someProps1} />
<Baby {...someProps2} />
{someCondition ? <Baby {...someProps3} /> : null}
</>
);
}
function SomeOtherComponent(props) {
return <Mother><Stepmother {...props} /></Mother>;
}
Now the Mother receives in its children only a JSX element for the Stepmother and can not parse the JSX elements for the Baby'ies. :(
So we return to my original question: I need to "render" Stepmother and then parse its internal JSX representation. But how can I do this?
P.S. I used functional components for brevity, but of course, all examples could use class components as well.
Thank you.
Don't do that.
I strongly encourage you to just rethink this solution altogether, ESPECIALLY if
It is used primarily as a configuration carrier.
...but.
So this kinda works however there's a couple of caveats:
if a component passed to that function is a class component and has some state, you won't be able to use any of it, in general it will probably cause a ton of issues that I'm not aware of
if a component passed is a function component, you can't use any hooks. It will just throw an error at you.
function render2elements(component, props) {
if (component.prototype.isReactComponent) {
return new component(props).render();
}
return component(props);
}
So if your "babies" are really simple this technically would work. But you just shouldn't refactor it the way you want and, again, ideally rethink this whole concept.

You specified `onScroll` on a <ScrollView> but not `scrollEventThrottle`

I am using Scrollview of react-native in my code.
<ScrollView style={styles.productlist} >
<CarouselComponent images={images}/>
</ScrollView>
Its working fine on an app, with no error, and no warning but in Console I am getting the below message repeatedly:
You specified onScroll on a but not scrollEventThrottle. You will only receive one event. Using 16 you get all the events but be aware that it may cause frame drops, use a bigger number if you don't need as much precision.
Don't know what is missing, I have not passed onScroll props but still getting this message.
Any suggestion...
My Carousel component Code is:
const renderImages = (image, index) => {
return (
<Image
key={index}
style={styles.carouselImage}
source={{ uri: image.large }}
/>
);
}
const CarouselComponent = (props) => {
const { images: { alternate = [] } = {} } = props;
if (alternate.length > 0) {
return (
<Carousel
delay={3000}
autoplay
style={styles.carouselLayout}
bullets
chosenBulletStyle={globalStyle.proDetCarSelectBullet}
bulletStyle={globalStyle.productDetailBullet}
bulletsContainerStyle={globalStyle.proDetCarBullet}
isLooped
currentPage={0}
>
{alternate.map((image, index) => renderImages(image, index))}
</Carousel>
);
}
return null;
}
You are probably using an older version of react-native-looped-carousel. On github there is a issue, which was fixed 27 days ago, describing your problem.
Fix:
Updating to the latest version of react-native-looped-carousel should resolve your issue. As an alternative you can fix the error by manually adding the scrollEventThrottle. See here.
There is nothing wrong in your code, the problem is contained into react-native-looped-carousel as an issue states here: https://github.com/phil-r/react-native-looped-carousel/issues/269
I suggest you to search for another library. React-native's code keep growing in a very fast way and every library should be updated frequently.
Just to learn something new, the scrollEventThrottle prop defines how many times the onScroll event will be fired while you scrolling. The bigger the number is, less times the event will be fired. 16 is most precise value.
Actually, the main ScrollView component needs the following code:
<ScrollView
scrollEventThrottle={16}
~~~

Understanding React refs - why is my reference null here?

I have a use-case where a React ref makes sense.
I've tried a few different ways of implementing them, and in this case integrating them with hammerjs.
I'm mostly going off of this question:
adding hammerjs to a react js component properly
My return method in my render is as such:
return (
<div className={"App card-row card-color " + this.props.className} ref={
(el) => this._slider = el
}>
{this.state.bubblemsg ? (
<NotifBubble message={this.state.bubblemsg} merchant={this.props.merchant.merchant}/>
) : (
null
)}
<ScrollMenu
data={this.state.list}
inertiaScrolling={true}
transition={.1}
inertiaScrollingSlowdown={.000001}
/>
</div>
);
Which I would think would attach my div element as a reference.
In my componentDidMount() method, I am then attaching it to hammer:
componentDidMount() {
this.hammer = Hammer(this._slider)
this.hammer.on('swipeleft', console.log("swipe left"));
this.hammer.on('swiperight', console.log("swipe right"));
}
However, I am getting the error:
TypeError: Cannot read property 'addEventListener' of undefined
And this is directly related to Hammer, and thus the reference I assume.
So what am I doing wrong with my references? I don't totally understand how they're supposed to work and the React tutorial explanation wasn't super clear, so a thorough explanation would be useful.
I think the problem is that in the listening of the hammer you have to pass a function to be called, try inserting an arrow function to log
componentDidMount() {
this.hammer = Hammer(this._slider)
this.hammer.on('swipeleft', () => console.log("swipe left"));
this.hammer.on('swiperight', () => console.log("swipe right"));
}

Resources