React/Redux/ReactDnd - Error: removeComponentAsRefFrom - javascript

I am trying to apply a basic example of react DnD to my project (as a proof of concept) and am running into some issues. I am using this example - https://github.com/gaearon/react-dnd/tree/master/examples/02%20Drag%20Around/Naive . which just let you drag around some divs inside a box.
So I have an outer component (Note: this is a few component levels up from the actual drag component) which is basically the whole page (this is just for testing a POC at first) which looks like so:
import { DropTarget, DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
const boxTarget = {
drop(props, monitor, component) {
const item = monitor.getItem();
const delta = monitor.getDifferenceFromInitialOffset();
const left = Math.round(item.left + delta.x);
const top = Math.round(item.top + delta.y);
component.moveBox(item.id, left, top);
}
};
// eslint-disable-next-line new-cap
#DragDropContext(HTML5Backend)
// eslint-disable-next-line new-cap
#DropTarget('CLA_DRAG', boxTarget, (connect) => ({
connectDropTarget: connect.dropTarget()
}))
export default class GenericPlatformComponent extends React.Component {
...
render() {
const { connectDropTarget } = this.props;
return connectDropTarget(
<div>
{this.getBuilders()}
</div>
);
}
}
So pretty close to the examples container, just using a string for now instead of that constant in #DropTarget . The getBuilders just renders other components inside. I Ran this component before creating the DragSource component and everything was running fine.
So, a few components down I just added the react DnD syntax to the component I want to be draggable like so :
import { DragSource } from 'react-dnd';
const boxSource = {
beginDrag(props) {
const { id, left, top } = props;
return { id, left, top };
}
};
// eslint-disable-next-line new-cap
#DragSource('CLA_DRAG', boxSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging()
}))
export default class SearchResult extends React.Component {
constructor(props) {
super(props);
}
render() {
const { connectDragSource } = this.props;
return connectDragSource(
<div key={this.props.key}>
<Row>
<Col xs={2} sm={2} md={1} lg={1} >
<div style={tempThumbnail}>
Picture Here
</div>
</Col>
<Col xs={10} sm={10} md={11} lg={11} >
<DescriptionBlock result={this.props.result} {...this.props} />
</Col>
</Row>
</div>
);
}
}
So with all this, I am getting this error on the console (the app is stopping rendering too).
bundle.js:29605 Uncaught (in promise) Error: removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: react-refs-must-have-owner).(…)
What is strange is the dragsource isn't even called onto the dom yet, so I have no idea where to start with this error. Any input or suggestions would be greatly appreciated. Thanks!

Maybe you omitted it, but you should be importing React in both of your examples:
import React from 'react'

Related

Fixing 'index.js:1 Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code' in react

I have this higher order component which recieve a comp of volunteer for ex and an action, and then render a table with the volunteer info:
the volunteer comp code:
class Volenteer extends Component {
render() {
const title = 'רשימת מתנדבים';
const mode = 'work';
return (
<EntityTable
columns = {columns}
title = {title}
mode = {mode}
promiseProps = {this.props}
/>
)
}
}
export default WithEntity(Volenteer, requestVolunteerData() );
and the HOC code is:
import React, {Component} from 'react';
import { connect } from 'react-redux';
const WithEntity = (EntityComponent, action) => {
const mapStateToProps = state => {
return {
isPending: state.requestEntitiesReducer.isPending,
entities: state.requestEntitiesReducer.entities,
error: state.requestEntitiesReducer.error
}
}
const mapDispatchToProps = dispatch => {
return {
onRequestEntities: () => dispatch(action)
}
}
class WithEntity extends Component {
componentDidMount () {
this.props.onRequestEntities();
}
render() {
return (
<EntityComponent {...this.props} />
)
}
}
return connect(mapStateToProps, mapDispatchToProps)(WithEntity);
}
export default WithEntity;
it works fine but i am getting this warning:
There are similiar question about this , but did not find the solution there, also i have tied to implement componentDidUpdate but it fails. is there a problem by using componentDidMount life cycle?
Edit:
the DataProvider, FilterProvider or SortProvider, the components that mentioned in the message, comes from the react-bootstrap-table-2 comp:
const Table = ( {data, columns, mode} ) => {
<div className = 'table-responsive fixed word-wrap scroll mapping_table'>
<BootstrapTable
bootstrap4
keyField={'id'}
data={data}
columns={columns}
responsive = {true}
condensed
hover
pagination={ paginationFactory()}
filter={ filterFactory() }
defaultSortDirection="asc"
/>
</div>
}
export default Table;
here is a picture of the components list:
This is a known problem in react-bootstrap-table-2 component and has nothing to do with the HOC code you've pasted.
Your options are:
ignore the warning and hope nothing breaks
do the work to fix the library for more modern React and maybe put in a PR - wait for someone else to do the work
switch to another library

Use imported function in return method (invalid hook call, react js)

Wassup Guys,
I have a reusable component, that translates keys into a choosen language through keynames as string or a binded var.
Usually I use a tag for this, but because of different reasons I am switching/replacing current translations with {t('...')}.
Here is the code of the component:
import React from 'react';
import { useTranslation as defaultTranslation } from 'react-i18next';
import i18next from 'i18next';
export const useTranslation = (ns = 'common', options) => {
return defaultTranslation(ns, {
useSuspense: false,
...options,
});
};
export const withTranslation = (Component, ns, options) => {
const TranslatedHOC = (props) => {
const translationProps = useTranslation(ns, options);
return <Component {...translationProps} {...props} />;
};
return TranslatedHOC;
};
export const getCurrentLanguage = () =>
i18next.language || localStorage.getItem('language') || 'de-DE';
First of all I define the const for the used imported function:
const {t} = useTranslation();
normal case: importing my component in the file, where I want to use it and add code above.
Code of my component, where I want to replace the Tags.
// Import React Table
import ReactTable from 'react-table';
import 'react-table/react-table.css';
import LocalizedText from '#components/i18n/LocalizedText';
class T extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
pages: null,
loading: true,
};
this.fetchData = this.fetchData.bind(this);
}
fetchData(state, instance) {
this.props.onFetchData(state, instance).then(() => {
this.setState({
loading: false,
});
});
}
render() {
return (
<ReactTable
{...this.props}
previousText={
<LocalizedText textKey="caseoverview.orderproduct.back" />
}
nextText={
<LocalizedText textKey="caseoverview.orderproduct.continue" />
}
loadingText={<LocalizedText textKey="loading" />}
noDataText={<LocalizedText textKey="placeholders.nodata" />}
pageText={
<LocalizedText textKey="reservationcalculator.search.result.page" />
}
ofText={<LocalizedText textKey="from" />}
rowsText={<LocalizedText textKey="rows" />}
className="case-search-table"
/>
);
}
}
export default T;
...
previousText={
<LocalizedText textKey="caseoverview.orderproduct.back" />
}
...
should change to:
...
previousText={
t('caseoverview.orderproduct.back')
}
...
The problem is, that I can't use the code quoted above without getting any issues regarding invalid hook calls. If I move it out somehow, I get errors telling me that my 't' is either not defined or an unexpected token. Could someone help me out? Searched online for solutios without any result.
A hook can only be used in a functional component. You can change this class component to a functional component, or you can use react-i18next's withTranslation HOC to wrap your class component. See https://react.i18next.com/latest/withtranslation-hoc#when-to-use
#kevin asworth answer helped me out.
Using withTranslation with passing t as prop
const {t} = this.props;
inside the render method worked for me.

Use hook in class component React

Hello I have checked the few articles on the subject, but I was not successful in doing the same.
I would like if possible an example if possible.
import React from 'react'
import { useInView } from 'react-intersection-observer'
const Component = () => {
const [ref, inView, entry] = useInView({
/* Optional options */
threshold: 0,
})
return (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
)
}
it's ok
class Nameclasse extends Component
{
constructor(props)
{
super(props);
const [ref, inView, entry] = useInView({
/* Optional options */
threshold: 0,
})
}
render()
{
return (<div></div>);
}
}
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
In my opinion React Hook is a option to use states in situations where you won`t like to use (react) components. Therefore the syntax should look like a this:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
const [ref, inView, entry]: useInView({
/* Optional options */
threshold: 0,
})
};
}
render() {
return (
<>
</>
);
}
}
I don`t if this is working (no time), but maybe its worth a try or some other more experienced coder could help you :)
source: https://reactjs.org/docs/hooks-state.html
State management with a Hook is exclusive to development by function, for any change of a state in a class you must go through the inherited function this.setState();
Function ex :
function Counter() {
const [count,setCount] = useInView(0)
return (<div> <button onclick={() => {setCount(count + 1)}}>Click me + 1</button> {count}</div>);
}

How to Programmatically Provide and Consume Context?

So my question is a simple one. In React js I want to pass some states and handlers from a parent to its 3rd grandchild using Context. I have implemented this within the jsx but I want to use the states within the javascript o that I have some logic before I completely output my states.
I have divided my question into 2 parts. 1.) What I have done so far. 2.) What I want to do essentially.
1.)
// this file just stores the Context
MyContext.js
import React, { Component } from 'react';
export const MyContext = React.createContext();
MyProvider.js // this class is used by the parent and the child to have access to the provider
import React, { Component } from 'react';
import {MyContext} from '../MyContext'
class MyProvider extends Component {
state = {
name: 'Wes',
age: 100,
cool: true
}
render() {
return (
<MyContext.Provider value={{
state: this.state,
growAYearOlder: () => this.setState({
age: this.state.age + 1
})
}}>
{this.props.children}
</MyContext.Provider>
)
}
}
export default MyProvider;
// Ok so now I am basically skipping the parent and showing you the consumer grand-child
Person.js
import React, { Component } from 'react';
// first we will make a new context
import { MyContext } from '../MyContext';
class Person extends Component {
render() {
return (
<div className="person">
<MyContext.Consumer>
{(context) => (
<React.Fragment>
<p>Age: {context.state.age}</p>
<p>Name: {context.state.name}</p>
<button onClick={context.growAYearOlder}>🍰🍥🎂</button>
</React.Fragment>
)}
</MyContext.Consumer>
</div>
)
}
}
export default Person;
2.)
// Ok so as you can see here I have had to immediately use the context.growAYearOlder. What I want to do instead is have control of it using javascript and modify it as desired; So something like this:
Child.js
const parentContext = MyContext.getContext();
if(somethingHappens){
parentContext().growAYearOlder();
}
return(
// The now rendered component
);
I tried something like this but it doesnt work:
MyContext.Consumer.context.growAYearOlder();
There are many similar questions with proper answers, docs, examples and so on - but this question kept popping up for me.
So, in case you want to get the context value and use it within your component's render() just import it (export context itself not only provider) and use _currentValue e.g.
const contextData = MyContext._currentValue;
Note that you still have to wrap your components with your given context provider.
Also note that for function components, you need to use useContext e.g.
const contextData = useContext(MyContext);
And for class components you can assign the context to a static var and then use it e.g.
class Main extends React.Component(){
static contextType = MyContext;
componentDidMount(){
const contextData = this.context;
}
render() {
return (
<p>Hey</p>
);
}
Note that the static var has to be called contextType otherwise this.context won't hold the MyContext data.
I've based my answer solely from the docs itself(https://reactjs.org/docs/context.html#updating-context-from-a-nested-component)
import React, { Component } from 'react';
import { MyContext } from '../MyContext'
class MyProvider extends Component {
constructor(props) {
super(props)
// I've moved the state declaration inside the constructor
this.state = {
name: 'Wes',
age: 100,
cool: true
}
// moved the function here and added prevState
this.growAYearOlder = () => {
this.setState(prevState => ({
age: prevState.age + 1,
}))
};
}
render() {
return (
<MyContext.Provider value={{
state: this.state,
growAYearOlder: this.growAYearOlder,
}}>
{this.props.children}
</MyContext.Provider>
)
}
}
export default MyProvider;

React propTypes component class?

How can I validate that the supplied prop is a component class (not instance)?
e.g.
export default class TimelineWithPicker extends React.PureComponent {
static propTypes = {
component: PropTypes.any, // <-- how can I validate that this is a component class (or stateless functional component)?
};
render() {
return (
<this.props.component {...this.props} start={this.state.start}/>
);
}
}
For anyone using PropTypes >= 15.7.0 a new PropTypes.elementType was added in this pull request and was released on february 10, 2019.
This prop type supports all components (native components, stateless components, stateful components, forward refs React.forwardRef, context providers/consumers).
And it throws a warning when is not any of those elements, it also throws a warning when the prop passed is an element (PropTypes.element) and not a type.
Finally you can use it like any other prop type:
const propTypes = {
component: PropTypes.elementType,
requiredComponent: PropTypes.elementType.isRequired,
};
EDITED: Added React's FancyButton example to codesandbox as well as a custom prop checking function that works with the new React.forwardRef api in React 16.3. The React.forwardRef api returns an object with a render function. I'm using the following custom prop checker to verify this prop type. - Thanks for Ivan Samovar for noticing this need.
FancyButton: function (props, propName, componentName) {
if(!props[propName] || typeof(props[propName].render) != 'function') {
return new Error(`${propName}.render must be a function!`);
}
}
You'll want to use PropTypes.element. Actually... PropType.func works for both stateless functional components and class components.
I've made a sandbox to prove that this works... Figured this was needed considering I gave you erroneous information at first. Very sorry about that!
Working sandbox example!
Here is the code for the test in case link goes dead:
import React from 'react';
import { render } from 'react-dom';
import PropTypes from "prop-types";
class ClassComponent extends React.Component {
render() {
return <p>I'm a class component</p>
}
}
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
const FSComponent = () => (
<p>I'm a functional stateless component</p>
);
const Test = ({ ClassComponent, FSComponent, FancyButton }) => (
<div>
<ClassComponent />
<FSComponent />
<FancyButton />
</div>
);
Test.propTypes = {
ClassComponent: PropTypes.func.isRequired,
FSComponent: PropTypes.func.isRequired,
FancyButton: function (props, propName, componentName) {
if(!props[propName] || typeof(props[propName].render) != 'function') {
return new Error(`${propName}.render must be a function!`);
}
},
}
render(<Test
ClassComponent={ ClassComponent }
FSComponent={ FSComponent }
FancyButton={ FancyButton } />, document.getElementById('root'));

Categories

Resources