Trying to create a draggable table/list and it gives me error saying 'provided.innerRef has not been provided with a HTMLElement.' - material-ui

I am trying to create a draggable list using Material UI and react-beautiful-dnd. I followed the tutorial on their page and created this-
function DraggableList(props) {
const { classes, tableHeaders, tasksList } = props;
return (
<div>
<Droppable droppableId="id">
{(provided) => (
<div ref={provided.innnerRef} {...provided.droppableProps}>
{tasksList && tasksList.slice(0,5).map((row, index) => (
<Draggable draggableId={row.id} index={index}>
{(provided)=> (
<div index={index} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
<Paper className={classes.root} key={row.id}>
<Grid container xs={12} className={classes.topContainer}>
<Grid item xs={2}>
<IconButton><DragIndicatorIcon className={classes.dragIcon}/></IconButton> </Grid>
<Grid item xs={10}>
<Typography className={classes.activity} variant="body2">{row.name}</Typography>
</Grid>
</Grid>
</Paper>
</div>
)}
</Draggable>
))}
</div>
)}
</Droppable>
</div>
);
}
It keeps giving me
Error: Invariant failed:
provided.innerRef has not been provided with a HTMLElement.
You can find a guide on using the innerRef callback functions at:
https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/guides/using-inner-ref.md
error though I am setting innerRef on a 'div' . What is the mistake here

Typo:
ref={provided.innnerRef}

I had the same problem, but my solution was quite different. I made the silly mistake of using curly bracket instead of parentheses. So I did:
{(provided) => {
And not:
{(provided) => (
No error indications whatsoever other than "provided.innerRef has not been provided with a HTMLElement."

You put
provided={provided}
in the same div it will start working. I also had the same issue but it got resolved with this.

I had the same problem and I used styled-components. I just set the ref prop on the styled-component element and it worked for me.
I mean this:
const StyledElement = styled.div`
//the css goes in here
`;
<StyledElement ref={provided.innerRef} {...provided.droppableProps}>
//The rest of the code goes here
<StyledElement/>

Related

Vite React VScode. Errors not underlined, no warnings etc

I've just started assembling my projects with Vite. And noticed that VSCode doesn't inform you about your mistakes anymore. Component just doesn't work properly and I don't see any underlines. So I did something like this:
const BasketItem = ({ removeFrromOrder, id, name, price, quantity }) => {
return (
<ListItem>
<Typography variant='body1'>
{name} {price}руб x{quantity}
</Typography>
<IconButton onClick={() => removeFrromOrder(id)}>
<Close />
</IconButton>
</ListItem>
);
};
<BasketItem key={item.name} removeFromOrder={removeFromOrder} {...item} />
Nothing is underlined. Usually the last string of code would be underlined since component expects removeFrromOrder with two 'r' (which is typo :)
Any ideas why it would be happening? Is it connected with Vite in any way?

Unable to see results with AsyncTypeahead with multiple option and renderInput

I'm trying to use a custom Input component on a Typeahead with the multiple option set. I see in the docs it says to "handle the refs" correctly, but I see no examples of how this is done. I'm not sure what to pass into referenceElementRef. Everything I've tried so far just doesn't render the options as I type. I see them in the DOM, but the opacity of the .rbt-menu is set to 0, so they're basically hidden.
Here's my code so far:
const divRef = React.useRef(null);
return (
<Col>
<div ref={divRef}>
<span className="uppercase">
<FormattedMessage id="d.customer" defaultMessage="Customer" tagName="h4" />
</span>
<AsyncTypeahead
multiple
id="customer-filter-input"
inputProps={{
'aria-label': 'Customer search',
style: { fontSize: '14px' },
}}
key={'customer-input'}
minLength={4}
isLoading={props.isLoadingcustomersSuggestions}
delay={300}
onSearch={(term: string) => handleFilterInputs(term, 'customers')}
size={'lg'}
options={dataSource}
labelKey={'defaultMessage'}
placeholder={intl.formatMessage({
id: 'companyName',
defaultMessage: 'Company name',
})}
onChange={(filterItem: any) => handleAutocompleteUpdate(filterItem, 'customer')}
renderInput={({ inputRef, referenceElementRef, ...inputProps }: any) => (
<Input
{...inputProps}
style={{ position: 'relative' }}
ref={(input: any) => {
inputRef(input);
referenceElementRef(divRef); // What do I put here?
}}
/>
)}
/>
</div>
</Col>
);
And this is what renders in the DOM after I type in the Typeahead and get results:
Any ideas or working examples of Typeahead using multiple and renderInput together?
EDIT:
Here's a codesandbox of what I'm seeing. I also see that the problem is also happening when multiple is NOT set. It seems to be an issue with using renderInput. Is it required that I also use renderMenu?
https://codesandbox.io/s/react-bootstrap-typeahead-async-pagination-example-forked-3kz3z
If you upgrade the typeahead version in your sandbox to the latest version (v5.1.1) and pass the input element to referenceElementRef, it works (note that you need to type some characters into the input for the menu to appear):
// v5.0 or later
renderInput={({ inputRef, referenceElementRef, ...inputProps }) => (
<Input
{...inputProps}
ref={(input) => {
inputRef(input);
referenceElementRef(input);
}}
/>
)}
The menu is rendered in relation to the referenceElementRef node by react-popper. In most common cases, the reference node will be the input itself. The reason there's both an inputRef and a referenceElementRef is for more complex cases (like multi-selection) where the menu needs to be rendered in relation to a container element around the input.
If using v4 of the component, the approach is similar, but the ref to use is simply called ref:
// v4
renderInput={({ inputRef, ref, ...inputProps }) => (
<Input
{...inputProps}
ref={(input) => {
inputRef(input);
ref(input);
}}
/>
)}

React: how to use child FormItem components without getting Warning: validateDOMNesting: <form> cannot appear as a descendant of <form>

Given the parent component, I am using a child component DynamicFieldSet that is a grouping of FormItems. But I am receiving the error:
Warning: validateDOMNesting(...): <form> cannot appear as a descendant of <form>. See CreateTopic > Form > form > ... > DynamicFieldSet > Form > form.
I have tried to remove the <Form> </Form> tags in my child component, but then it is a compile error.
Is there a way I can disable rendering of the child Form view?
Parent component
class CreateTopic extends React.Component {
render() {
return (
<div className="create-topic-container">
<h3>Create an event</h3>
<Form onSubmit={this.handleSubmit}>
<FormItem>...</FormItem>
<FormItem>...</FormItem>
<FormItem>...</FormItem>
<FormItem
{...formItemLayout}
label="Results"
style={{ marginBottom: SPACING_FORM_ITEM }}
>
{getFieldDecorator('results', {
rules: [
{
required: true,
message: 'Results cannot be empty.',
},
],
})(<DynamicFieldSet
form={this.props.form}
/>)}
</FormItem>
</Form>
</div>
);
}
}
DynamicFieldSet - Child component
export class DynamicFieldSet extends React.Component {
render() {
getFieldDecorator('keys', { initialValue: ['0', '1'] });
const keys = getFieldValue('keys');
const formItems = keys.map((k, index) => {
return (
<FormItem
{...formItemLayoutWithOutLabel}
required={false}
key={k}
>
{getFieldDecorator(`results[${k}]`, {
validateTrigger: ['onChange', 'onBlur'],
rules: [
{
required: true,
whitespace: true,
message: 'Result name cannot be empty.',
},
{
validator: this.validateLength,
},
],
})(<Input placeholder={`Result #${index + 1}`} style={{ width: '80%', marginRight: 8 }} />)}
{keys.length > 2 ? (
<Icon
className="dynamic-delete-button"
type="minus-circle-o"
disabled={keys.length === 1}
onClick={() => this.remove(k)}
/>
) : null}
</FormItem>
);
});
return (
<Form>
{formItems}
<FormItem {...formItemLayoutWithOutLabel}>
{keys.length < 10 ? (
<Button type="dashed" onClick={this.add} style={{ width: '80%' }}>
<Icon type="plus" />Add Result
</Button>
) : null}
</FormItem>
</Form>
);
}
}
I faced this issue when using ant design table and turns out its not ant design which throws the warning. It's the web standards description
"Every form must be enclosed within a FORM element. There can be several forms in a single document, but the FORM element can't be nested."
So, there should not be a form tag inside a form tag.
To solve the issue (in our case), remove the Form tag inside the DynamicFieldSet "return" and replace with a div tag
Hope it helps :)
You can portal a form like this:
import Portal from '#material-ui/core/Portal';
const FooComponent = (props) => {
const portalRef = useRef(null);
return <>
<form>
First form
<div ref={portalRef} />
</form>
<Portal container={portalRef.current}>
<form>Another form here</form>
</Portal>
</>;
}
In the example above I use the react material-ui Portal component. But you can try to implement it with React Portals as well
If you're using MUI, the Box component contains an attribute that identifies them as any native HTML container; form is one of them. E.g:
<Box
xs={6}
sx={{
"& > :not(style)": { m: 1, width: "25ch" },
}}
component="form"
noValidate
autoComplete="off"
>
In such case, we just need to delete that attribute, it will default to a DIV. The form will continue to work as expected, and the error will disappear off the console.
In my case this is occur bcoz of i declared <form> inside another <form/> tag.

Getting a dialog on click of Edit Button on admin-on-rest

I am working on an application using admin-on-rest framework. For editing an entry on a Resource we provide XXXEdit, XXXShow, XXXCreate props to it. My requirement is that when I click on an Edit button in List view on any entry I should get a Dialog box with the parameters in XXXEdit instead of going to a new page. I tried doing this by using a Dialog in XXXEdit component
<Edit title={<RoleTitle />} {...props}>
<SimpleForm>
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={true}
>
<TextInput source="id" />
<TextInput source="name" validate={required} />
.
.//some more fields
</Dialog>
</SimpleForm>
</Edit>
I get errors like The TextInput component wasn't called within a redux-form
If I use a DisabledInput then I get an error cannot read value of undefined
How do I go on with this?
I do not think you can use Simpleform for this. You will need to create a custom Form using Redux-Form. Look at the bottom answer that documents the final answer.
This might help you
How to richly style AOR Edit page
Instead of creating a page. You are creating a component that connects to the Redux state and displays as a dialog box.
I tried to resolve this using HOC and react-router.
I created a button using AOR button and provided a containerElement
containerElement={
<Link
key={record.id}
to={{
...{
pathname: `${basePath}/${encodeURIComponent(record.id)}`
},
...{ state: { modal: true } }
}}
/>
}
I created a route like this where DialogRoleEdit is an AOR edit component wrapped with a dialog HOC below .
<Route
exact
path="/roles/:id"
render={routeProps => {
return !!(
routeProps.location.state && routeProps.location.state.modal
) ? (
<Restricted authClient={authClient} location={routeProps.location}>
<div>
<RoleList resource={"roles"} {...routeProps} />
<DialogRoleEdit resource={"roles"} {...routeProps} />
</div>
</Restricted>
) : (
<Restricted authClient={authClient} location={routeProps.location}>
<RoleEdit resource={"roles"} {...routeProps} />
</Restricted>
);
}}
/>
Finally an HOC
handleClose = () => {
this.props.history.goBack();
};
render() {
const actions = [
<FlatButton label="Cancel" primary={true} onClick={this.handleClose} />
];
return (
<Dialog>
<WrappedComponent/>
</Dialog>
)
}
We need to provide edit prop for this resource in App.js
edit={DialogUserEdit}

RaisedButton fullWith doesn't expand anymore in v0.15

The RaisedButtons components don't go fullWidth anymore in the version v0.15 of material-ui, this worked in the v0.15-beta. I solved it by adding minWidth: '100%' to the element. Is this intentional or am I doing something wrong here ?
const buttonStyle = {
minWidth:'100%',//<- works with minWidth set
};
return (
<MuiThemeProvider muiTheme={muiTheme}>
<div style={style}>
<SelectField max-height={200} style={selectStyle} fullWidth={true} onChange={this.onFondsSelect} value={displayValue} id="fonds-selection">
{this.menuItems}
</SelectField>
<RaisedButton style={buttonStyle} onClick={this::this.startClick} fullWidth={true}>Button 1</RaisedButton><br/>
<RaisedButton style={buttonStyle} onClick={this.resetStart} fullWidth={1}>BUtton 2</RaisedButton>
</div>
</MuiThemeProvider>
);
This bug was introduced in material-ui v15
issue => github.com/callemall/material-ui/issues/4226
However as you can see in the issue comments, the fullWidth may be deprecated in v16 in favour of the style object. So you are doing it the right way.