"TypeError: Object(...) is not a function" error when trying to use Semantic UI React Dropdown - reactjs

I'm getting an error of "TypeError: Object(...) is not a function" on "ClientApp/node_modules/semantic-ui-react/dist/es/modules/Dropdown/Dropdown.js line 81" when I try to create a new instance of the Semantic UI React dropdown in my react application. I have even copied the code over, only changing variable names, from a project that a colleague worked on, and neither of us can seem to determine the source of the error.
I have tried following the guides on semantics website to no avail. I have copied the code with the includes from a working and existing project.
handleSelectClub = (e, data) => {
const club = this.state.clubList[data.value];
this.setState({
clubId: club.id,
name: club.name
});
}
render() {
var clubs;
let selectClub = null;
if (this.state.clubList.length > 0)
{
clubs = this.state.clubList.map((opt, i) => ({
key: opt.id,
text: opt.name,
value: i
}));
selectClub =
<div>
<div className="form-group">
<Dropdown placeholder='Search Clubs' search selection options={clubs} onChange={this.handleSelectClub} />
</div>
</div>
}
return (
<form className="club-add-form" onSubmit={this.handleSubmit}>
<h1>Add a New Club</h1>
{selectClub}
</form>
);
}
I just want the dropdown to be part of a pretty basic form for adding an entry to a database.

I managed to reproduce this error in 0.87.1 of Semantic UI, I downgraded to 0.84 and the issue is not there.
Hope it helps.

Related

Having a problem with PrimeReact Dropdown

I am still a novice in React Js and recently I have been developing using PrimeReact. The Forms and DataTables are doing well for me but I cant seem to figure out how deal with the Dropdown. My state is managed by redux and after mapStateToProps I and loading my data using componentDidMount I can console.log and see my data array. With a normal react select input I have been using the following code:
const {accounttypes} = this.props;
console.log(accounttypes)
let typesOptions = accounttypes.length > 0
&& accounttypes.map((item, index) => {
return (
<option key={item.id } value={item.id}>{item.name}</option>
)
}, this);
This works as an option as I can post to my backend. However I would want to use PrimeReact for all my forms and I have been struggling on how to go about it. The following has been my attempt and its giving me a headache:
<div className="p-field p-col-12 p-md-4">
<Dropdown
value={account_type}
optionValue = {accounttypes.id}
optionLabel = {accounttypes.name}
options={accounttypes}
onChange={this.onTypeChange}
placeholder="Select an Acco"
autoFocus = {true}
editable={true}
/>
</div>
account_type is the name of my field and my django model references the accountytpe model and would like to capture account_type whilst creating an Account. May someone help. And thanks in advance
optionLabel and optionValue should point to equivalent properties of your object. In your case I guess the correct way is this
optionValue="id"
optionLabel="name"

React Bootstrap 3 - FormControl.Feedback messaging

I'm trying to use React Bootstrap V3's FormControl.Feedback to display different error messages similar to how its done in Bootstrap v4, is this possible? The only supporting documentation I've found is that its used to simply display an icon in the forms input area?
My current thought is I can use the validationState, which my handleAction method will set to one of either null, success, or error. Based on that state, is there a tag or something I can set in the FormControl block to display various messages based on the state?
<FormGroup controlId="formBasicText" validationState={this.state.nameState} bsClass='form-group required'>
<ControlLabel>Name</ControlLabel>
<FormControl maxLength='4000' name="name" type="text" value={this.state.name} placeholder="Name" onChange={this.handleChange} onBlur={this.handleChange}/>
<FormControl.Feedback/>
<HelpBlock className="text-danger">{this.state.nameError}</HelpBlock>
</FormGroup>
I have done some research and I found that the form validation was not in bootstrap v3. As React-bootstrap v(0.x) was based on bootstrap v3 and they have manually implemented icon-based form validation.
To implement form validation, you can define your own wrapper component.
let's say the component name is ValidationMessage
Sending custom message that you want to show based on state(Basic one)
const ValidationMessage = ({type, message, ...props}) => (
// will not render when type is null or undefined
type ? <div className=`validation-msg-${type}`>{message}</div> : null
)
and you can use it like below
<ValidationMessage type='success' message= "custom message for success'/>
Else you can make it little more usable like below
const ValidationMessage = ({type, message, ...props}) => {
const getMessage = type => {
// Define fixed messages that you can use everywhere
switch(type) {
case 'error'
return 'error text';
case 'warning'
return 'warning text';
case 'success'
return 'success text';
default:
return;
}
}
// will not render when type is null or undefined
return ( type ? <div className=`validation-msg-${type}`>{message || getMessage(type)}</div> : null)
}
and you can use it like below
<ValidationMessage type='success' />

How to render objects in hyperHTML

I've been asked to create a dropdown menu using hyperHTML for an exercise. I'm new to this framework and admittedly haven't found a great deal of material on hyperHTML online, but I've drafted a basic template based on what I've read. The problem is when I attempt to run my script using JSFiddle, it returns nothing from the entire div contents. Is anybody able to explain why this might be?
// HTML
<div id="drop"></div>
// JS
const modes = [{label: 'Driving', value: 'driving'},{label: 'Walking', value: 'walking'},{label: 'Cycling', value: 'cycling'}];
const render = hyperHTML.bind(document.getElementById('drop'));
render`
<h1>Hello, world</h1>
<select>
${modes.map(obj => wire(obj)`<option value="${obj.value}">${obj.label}</option>`)};
</select>
`;
Note: It is only when I add the code within the select parameters that JSFiddle refuses to render the div contents.
From what I can see from your code, you should have an error about the undefined wire, as you don't reference it anywhere.
This is the code I've used in this code pen, and everything works just fine.
const modes = [
{label: 'Driving', value: 'driving'},
{label: 'Walking', value: 'walking'},
{label: 'Cycling', value: 'cycling'}
];
const {bind, wire} = hyperHTML;
const render = bind(document.getElementById('drop'));
render`
<h1>Hello, world</h1>
<select>
${modes.map(obj => wire(obj)`<option value=${obj.value}>${obj.label}</option>`)};
</select>
`;

When trying to .append() some JSX to the body, I get [object Object]...

I have a multiple field form, and I'm trying to get a small Form Warning to display when the user inputs wrong information. The problem I'm having is that the form will not display the warning under the desired input correctly. I have been told that this is because the Form warning is positioned absolutely, and thus and parents along that way that are not-staticly-positioned will throw off the alignment.
The recommendation was to use .append or .after in componentWillMount() to put the Form Warning component in the body, so FormWarning component can be positioned absolutely to the window. Makes sense to me, but my attempts only being me an [object Object] at the very bottom of my page.
Can anyone provide any insight into why this is occurring and what I can do to fix it? I've tried multiple different ways of putting this, but nothing works. I always just get [object Object]
componentWillMount(){
this.formWarningToBody();
}
formWarningToBody = () => {
let form =[]
form.push(<FormWarning visible={this.state.formWarning.visible}
invalidInputID={this.state.formWarning.invalidInputID} text=
{this.state.formWarning.text}/>)
document.body.append({form})
}
render() {
if (this.state.isSubmitted) return <Redirect to="/order" />
let CustomTag = this.props.labels ? 'label' : 'span',
{ inputs, saveInputVal, styles, state } = this,
{ formWarning, submitting } = state,
{ invalidInputID, text, visible } = formWarning
return (
<div style={this.styles.formWrapper}>
{
typeof this.props.headerText === 'string'
? ( <h2 style={this.styles.formHeader}>{this.props.headerText}</h2> )
: this.props.headerText.map((text) => {
return <h2 key={text} style={this.styles.formHeader} className={'header'+this.props.headerText.indexOf(text)}>{text}</h2>
})
}
<form onSubmit={this.submit} style={this.styles.form}>
<FormOneInputs inputs={inputs} saveInputVal={saveInputVal} CustomTag={CustomTag} styles={styles} />
<button style={this.styles.button}>{this.props.buttonText}</button>
</form>
<Throbber throbberText='Reserving your order...' showThrobber={submitting} />
</div>
)
}
}
That's not how React works, you can't just push JSX to DOM because a JSX element is indeed an object, which is then rendered to HTML. You can use React Portals.
See docs: https://reactjs.org/docs/portals.html

react failed to compile module "conversational-form"

I'm trying to import this conversational-form npm module to my Create-React-App application and I've been getting compile errors on any attempts to do so.
Here is the exact error:
./~/conversational-form/dist/conversational-form.js
Module not found: Can't resolve 'conversationalform' in '/Users/user/Desktop/app_name/node_modules/conversational-form/dist'
So far I've tried to import it like
import ConversationalForm from 'conversational-form';
or using an absolute path to the js file in the "dist" folder, or even just including that js file in my project, but there are always compile errors.
The module is supposed to work with React.
Any ideas what may be causing this? Is perhaps Create-React-App incompatible with this? Should I just include the JQuery plugin from that module instead? Thank you.
UPDATE: Module seems to have been fixed now, but I still get errors when trying to adapt the example to a Webpack/React/Component structure
Error:
TypeError: Cannot read property 'setAttribute' of undefined
componentDidMount(){
13 | // add Conversational Form info
> 14 | this.refs.name.setAttribute('cf-questions', "Your name?");
15 | this.refs.email.setAttribute('cf-questions', "Your email?");
16 | this.refs.description.setAttribute('cf-questions', "What is description?");
CODE
import React, { Component } from 'react';
import { CSSTransitionGroup } from 'react-transition-group';
import ConversationalForm from './conversational_form';
class ConversationForm extends Component {
constructor(props) {
super(props);
this.cf = null; // <-- Conversational Form ref
}
componentDidMount(){
// add Conversational Form info
this.refs.name.setAttribute('cf-questions', "Your name?");
this.refs.email.setAttribute('cf-questions', "Your email?");
this.refs.description.setAttribute('cf-questions', "What is description?");
this.cf = window.cf.ConversationalForm.startTheConversation({
formEl: this.refs.form,
context: document.getElementById("cf-context"),
flowStepCallback: function(dto, success, error){
success();
},
submitCallback: function(){
// this callback could also be added to the React.createElement it self...
alert("You made it!")
console.log("Form submitted...");
}
});
}
render() {
var conversation;
if (this.props.visible) {
conversation =
<div>
<form id="form" ref={form => this.input = form} className="form">
<input type="text" ref={name => this.input = name} placeholder="Name (required)" defaultValue={this.props.name} />
<input type="email" ref={email => this.input = email} placeholder="Email" defaultValue={this.props.email} />
<textarea ref={description => this.input = description} placeholder="Description" defaultValue={this.props.description} />
<button type="submit">Submit</button>
</form>
<section id="cf-context" role="cf-context" cf-context>
</section>
</div>
}
return (
<CSSTransitionGroup
transitionName="success"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{conversation}
</CSSTransitionGroup>
)
}
}
export default ConversationForm;
The reason for the error is likely the way you are using your import. Since ConversationForm is probably one of several components in the module
you need to import it like this:
import {ConversationForm} from 'react-conversational-form';
---EDIT---
This is wrong, it seems like there is something fishy going on with the module itself.
---UPDATE---
The guys behind the module are super good and already issued a fix. The problem seemed to be with the way webpack handles dependencies. Now the module works as expected:
import cf from 'conversational-form'
var myForm = document.querySelector('#my-form');
var c = new cf.startTheConversation({formEl: myForm})

Resources