#StackBounty: #node.js #reactjs How can I initiate react to reload after a data change on the node js side?

Bounty: 100

Edit: It appears that my callback function from emit is never executed but not sure why.

So I added a calendar to react which changes the workout data to a specific date. When I change the date the data does change correctly. If I refresh the react web pages I get the updated data. I’m just a little confused on how to have node js initiate the data update in react. After changing the data I have node emitting to this socket…

//  Used for getting workouts for specific date. 
socket.on('GetWorkoutDate', async function (date) {
  workouts.getNewWorkouts(date.date)
  const screenWorkouts = workouts.current.filter(workout => workout.station == 1)
  console.log(screenWorkouts[0])
  socket.emit('UpdateWorkouts', screenWorkouts)
})

Then I the react side I tried something like this but no data change on the react.

import React, { Component } from 'react'
import { defaultTo } from 'ramda'
import openSocket from 'socket.io-client'

import './styles.css'

class Screen extends Component {
state = {
time: '',
rest: false,
workout: [],
queue: [],
}

componentDidMount() {
const screenNumber = this.props.match.params.id

this.socket = openSocket(`http://${window.location.hostname}:${process.env.REACT_APP_WEBSOCKET_PORT}`)
this.socket.on('connect', () => {
  this.socket.emit('joinRoom', 'screens')
  this.socket.emit('initScreen', screenNumber)
})
this.socket.on('timer', ({ time, rest }) => this.setState({ time, rest }))
this.socket.on('screenInfo', data => this.setState({ workout: defaultTo({}, data[0]) }))
this.socket.on('queueInfo', data => this.setState({ queue: defaultTo([], data) }))
this.socket.on('queue', ({ queue }) => this.setState({ queue: defaultTo([], queue[screenNumber - 1]) }))
this.socket.on('UpdateWorkouts', (updatedData) => this.handleUpdateWorkouts(updatedData));
}

componentWillUnmount() {
this.socket.close()
}

handleUpdateWorkouts = (updatedData) => {
this.setState({ workout: updatedData[0] })
 }

renderMovement = (movement, equipment) => {
if (!movement) return <noscript />

return (
  <div className="screenMove">
    {equipment && `${equipment.title} `}
    {movement.title}
  </div>
)
}

render() {
const { time, rest, workout, queue } = this.state
const variation = defaultTo({}, workout.variation)
const person1 = defaultTo({}, queue[0])
const person2 = defaultTo({}, queue[1])

return (
  <main className="screenWrapper">
    <div className="screenHeader">
      <span className="screenFirstUser">
        {(() => {
          if (person1.experiencelevel === 'novice') {
            //  light purple
            return (
              <div style={{color:'#BF5FFF', fontWeight: 'bold', display: 'inline-block'}}>{person1.firstname}</div>
            )
          } else if (person1.experiencelevel === 'beginner') {
            //   light blue
            return (
              <div style={{color:'#87CEFA', fontWeight: 'bold', display: 'inline-block'}}>{person1.firstname}</div>
            )
          } else if (person1.experiencelevel === 'intermediate') {
            return (
              <div style={{color:'orange', fontWeight: 'bold', display: 'inline-block'}}>{person1.firstname}</div>
            )
          } else if (person1.experiencelevel === 'advanced') {
            //  gym green
            return (
              <div style={{color:'#93C90E', fontWeight: 'bold', display: 'inline-block'}}>{person1.firstname}</div>
            )
          }else if (person1.experiencelevel === 'expert') {
            return (
              <div style={{color:'red', fontWeight: 'bold', display: 'inline-block'}}>{person1.firstname}</div>
            )
          }
        })()}
      </span>
      <span className={`screenTimer alt ${rest ? 'rest' : ''}`}>{time ? time : '0:00'}</span>
      <span className="screenSecondUser">
      {(() => {
          if (person2.experiencelevel === 'novice') {
            //    light purple
            return (
              <div style={{color:'#BF5FFF', fontWeight: 'bold', display: 'inline-block'}}>{person2.firstname}</div>
            )
          } else if (person2.experiencelevel === 'beginner') {
            //  light blue
            return (
              <div style={{color:'#87CEFA', fontWeight: 'bold', display: 'inline-block'}}>{person2.firstname}</div>
            )
          } else if (person2.experiencelevel === 'intermediate') {
            return (
              <div style={{color:'orange', fontWeight: 'bold', display: 'inline-block'}}>{person2.firstname}</div>
            )
          } else if (person2.experiencelevel === 'advanced') {
            //   gym green
            return (
              <div style={{color:'#93C90E', fontWeight: 'bold', display: 'inline-block'}}>{person2.firstname}</div>
            )
          }else if (person2.experiencelevel === 'expert') {
            return (
              <div style={{color:'red', fontWeight: 'bold', display: 'inline-block'}}>{person2.firstname}</div>
            )
          }
        })()}
      </span>
    </div>
    <p className="screenVariation">{variation.title}</p>
    <div className="screenMoves">
      {this.renderMovement(workout.movementOne, workout.equipmentOne)}
      {this.renderMovement(workout.movementTwo, workout.equipmentTwo)}
      {this.renderMovement(workout.movementThree, workout.equipmentThree)}
        </div>
      </main>
    )
  }
}

export default Screen

New to node and react. Appreciate the guidance!
Edited with updated code.


Get this bounty!!!

#StackBounty: #reactjs #react-redux #react-router #material-ui React router how to check form is dirty before leave page/route

Bounty: 50

Below are the package version I’m using.

React version - 16.13.1
react-router-dom version - 6.0.0-beta.0
react-redux version 7.2.0
Material UI version 4.11.0

How/What is best way to check the form isDirty (have changed) when the user trying to leave page? I would like to prompt "Are you sure want to leave…." if form isDirty.

I will fetch the data from useEffect() and redux reducer to render the UI.

Should I declare a variable to keep the original fetched data for dirty checking?

This is what I am doing, but not workable.

component.js

 useEffect(() => {
    props.fetchUserInfo();
 })

action.js

export function fetchUserInfo() {
 return (dispatch) => {
     dispatch({type: USER_INITIALSTATE, {Name: 'abc', Age: 20}} 
     )
 }
}

userReducer.js

const initialState = {
  processing: false,
  success: false,
  fail: false,
  Profile: {}
}
let oriState;
let State;
const UserReducer = (state = initialState, action) => {
  if (action.type === USER_INITIALSTATE) {
    oriState = {Profile: action.data};
    State = {...state, Profile: action.data};
    return {...state, Profile: action.data};
  } else if (action.type === OTHERS_ACTION) {
     //update field change
     return {...state, xxx}
  }
}
export const userIsDirty = state => {
  if (oriState && State) {
    return JSON.stringify(oriState.Profile) !== JSON.stringify(State.Profile);
  }
  return false;
};
export default UserReducer;

So in my component I call userIsDirty to return isDirty boolean, but I haven’t figure out how to catch the leave page event and use this method to do checking.

So how to detect page leaving? I tried something on useEffect return(component umount), but the props is not getting the updated INITIALSTATE state (meant I will get Profile: {}), because it only run once, but if I put the useEffect array argument, will have infinite loop(maybe I set it wrong?).

useEffect(() => {
    props.fetchUserInfo();
    return () => {
      console.log(props); //not getting initial state object
    };
  }, []);

Am I doing the correct way or wrong? What did I missed? Any better/correct solution to achieve what I want?

UPDATE: Maybe react-router is what I looking for, but how to implement the custom confirmation modal for dirty state?


Get this bounty!!!

#StackBounty: #javascript #reactjs #gatsby #gatsby-image #react-dom-server Injecting gatsby-image into html, which was created from mar…

Bounty: 50

I’m trying to inject some images into my pages created from markdown. I’m trying to do this using ReactDomServer.renderToString()

const componentCreatedFromMarkdown = ({data}) => {
...    
    useEffect(() => {
        const injectDivs = Array.from(document.getElementsByClassName('injectDivs'))
        injectDivs.forEach((aDiv) => {
            aDiv.innerHTML = ReactDOMServer.renderToString(<MyComponent args={myArgs} />)
        }
    })
...
}

MyComponent looks like this

<a className={args.className} href={args.link}>
    <Img
        style={{
            maxWidth: args.maxWidth,
            maxHeight: '100%',
            backgroundPosition: "center 25%"
        }}
        fluid={args.imgProps}
        backgroundColor={`#040e18`}
        objectFit="contain"
    ></Img>
</a>

The img is showing as a black box, if I right click the image I can open it in a new tab.


enter image description here


Get this bounty!!!

#StackBounty: #reactjs #asp.net-core #cookies #identityserver4 Authentication cookie disappears in react SPA after some time

Bounty: 50

We have an SPA, written in React together with ASP.net core for hosting.

To authenticate the app, we are using IdentityServer4 and use a cookie. The client is configured according to the sample, described here: https://github.com/IdentityServer/IdentityServer4/tree/main/samples/Quickstarts/4_JavaScriptClient/src

For authenticating a user, everythings works fine. It will be redirected to the login page. After signing in, redirection to the SPA is done. The authentiation cookie is set as expected with:

  • HttpOnly = true
  • Secure = true
  • SameSite = None
  • Expires / Max-age = one week from login time

In the ASP.net core project for the SPA, in Startup.cs, data protection is also configured as:

services.Configure<CookiePolicyOptions>(options =>
{                                                        
  options.CheckConsentNeeded = context => false;
  options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddDataProtection()
  .PersistKeysToFileSystem(new DirectoryInfo(_sharedAuthTicketKeys))
  .SetApplicationName("SharedCookieApp");

Our issue:

After about 30 minutes, the authentication cookie (and only that, other remains) is disappearing from the browser automatically. Then the user has to sign in again. Why does this happen together with the SPA?

In another MVC application, the user has to sign in again when the cookie expires, as expected.

Update

In the meantime I discovered that the cookie, while requesting https://ourdomain/.well-known/openid-configuration after 30 minutes idle time, has lost the values of Domain, Path, Expires/Max-Age, HttpOnly, Secure and SameSite.None. Those values have definitely been set after signing in.
The response cookie has the value of Expires/Max-Age set to a time in the past and therefore the cookie will be dropped by the browser.
Network traffic

Has anyone an idea, why those values got lost after some time?


Get this bounty!!!

#StackBounty: #reactjs #apollo #react-apollo #apollo-client How to handle cache update after mutation in multiple views?

Bounty: 150

This is more of a open question but hopefully it won’t get deleted.

I am using react and apollo although the question is more general.

Let’s say I have 3 distinct views in my app all using similar (but not the same) data.
All of them are using separate queries but each of the query uses common operation but with slightly different data returned.

Let’s say I have a mutation somewhere that adds something to data (think of a list of items and a new item being added).

Let’s say after mutation I want to update cache to reflect that change. I am using read/writeQuery to do the update.
With this setup I need to update 3 queries – this becomes a maintenance nightmare.

After some reading I figured I am doing this wrong – I have now created a single query – now I need to only update that single query after mutation and all of my views are updated automatically.
However the problem is that this query now has to download all the data that all 3 views combined need – feels like this is very inefficient, because some of the views will get data they’ll never use.

Is there a better way to do it?

Please note that read/writeFragment won’t work because they won’t update the underlying queries – check this answer for example: https://stackoverflow.com/a/50349323/2874705

Please let me know in comment if you need a more concrete example.

All in all I think in this setup I would just be better with a global state handling and avoid apollo cache all together – however I feel cheated cause apollo promised to solve the state problems 🙂


Get this bounty!!!

#StackBounty: #sharepoint-online #spfx-webparts #office-ui-fabric-react #reactjs Sticky Header in SPFx webpart

Bounty: 50

I have a SPFx webpart where I am using "DetailsList" to bind search data, I want to make header sticky while person scrolls the webpart, I have a search bar then dropdown and then grid in place, so how to add sticky header for only grid. Below goes my Details list added sticky but does not worked.

<div className={styles.row}>      
    <div className={styles.msCol}>
        <DetailsList
        items={FormattedArrayForDetailsList(items)}
        compact={true}
        columns={columns}
        className={styles.documentsList}
        constrainMode={ConstrainMode.unconstrained}
        selectionMode={SelectionMode.single}
        //disableSelectionZone={true}
        checkboxVisibility={CheckboxVisibility.always}
        getKey={this._getKey}
        setKey="set"
        layoutMode={DetailsListLayoutMode.fixedColumns}
        isHeaderVisible={true}
        selectionPreservedOnEmptyClick={false}
        enterModalSelectionOnTouch={true}
        ariaLabelForSelectionColumn="Toggle selection"
        ariaLabelForSelectAllCheckbox="Toggle selection for all items"
        selection={this._selection}
        onItemInvoked={this._onItemInvoked}
        onRenderMissingItem={this._onRenderMissingItem}
        onRenderDetailsHeader={
        // tslint:disable-next-line:jsx-no-lambda
        (detailsHeaderProps: IDetailsHeaderProps, defaultRender: IRenderFunction<IDetailsHeaderProps>) => (
        <Sticky>
        {defaultRender(detailsHeaderProps)}
        </Sticky>
        ) }
        //enableShimmer={!isDataLoading}
        />
    </div>
</div>   

enter image description here


Get this bounty!!!

#StackBounty: #javascript #reactjs #react-native #graphql #formik Button Disables After Running Query Once

Bounty: 50

I have a screen where the user inputs a phone number. I run a graphql query loadUsers according to the input and then display the search results via the showUsersfunction. It works fine on the first time. I get the results. However, after that, when the results are conditionally rendered, the search button becomes disabled. So if I want to type in a different phone number and hit the search button again, I can’t do this. Unless I exit the screen and then come back. How can I fix this?

Here’s what my code looks like:

export const AddContactTry: React.FunctionComponent = () => {
  const initialValues: FormValues = {
    phoneNumber: '',
  };

  const [isSubmitted, setIsSubmitted] = useState(false);
  const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
  const navigation = useNavigation();
  const validationSchema = phoneNumberValidationSchema;

  const [
    createUserRelationMutation,
    {
      data: addingContactData,
      loading: addingContactLoading,
      error: addingContactError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted: () => {
      Alert.alert('Contact Added');
    },
  });

  const showUsers = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      if (data) {
        return (
          <View style={styles.users}>
            {data.users.nodes.map(
              (item: { firstName: string; lastName: string; id: number }) => {
                const userName = item.firstName
                  .concat(' ')
                  .concat(item.lastName);
                return (
                  <View style={styles.item} key={item.id}>
                    <Thumbnail
                      style={styles.thumbnail}
                      source={{
                        uri:
                          'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
                      }}></Thumbnail>
                    <Text style={styles.userName}>{userName}</Text>
                    <View style={styles.addButtonContainer}>
                      <Button
                        rounded
                        style={styles.addButton}
                        onPress={() => {
                          addContact(Number(item.id));
                          setIsSubmitted(false);
                          setUserData(null);
                        }}>
                        <Icon
                          name="plus"
                          size={moderateScale(20)}
                          color="black"
                        />
                      </Button>
                    </View>
                  </View>
                );
              },
            )}
          </View>
        );
      }
    },
    [createUserRelationMutation, userData],
  );

  const addContact = React.useCallback(
    (id: Number) => {
      console.log('Whats the Id', id);
      createUserRelationMutation({
        variables: {
          input: { relatedUserId: id, type: RelationType.Contact, userId: 30 },
        },
      });
    },
    [createUserRelationMutation],
  );

  const getContactId = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      if (data) {
        if (data.users.nodes.length == 0) {
          Alert.alert('No User Found');
        } else {
          setUserData(data);
        }
      }
    },
    [addContact],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getContactId,
    onError: _onLoadUserError,
  });

  const handleSubmitForm = React.useCallback(
    (values: FormValues, helpers: FormikHelpers<FormValues>) => {
      setIsSubmitted(true);
      const plusSign = '+';
      const newPhoneNumber = plusSign.concat(values.phoneNumber);
      loadUsers({
        variables: {
          where: { phoneNumber: newPhoneNumber },
        },
      });
      values.phoneNumber = '';
    },
    [loadUsers],
  );

  return (
    <SafeAreaView>
      <View style={styles.container}>
        <View style={styles.searchTopContainer}>
          <View style={styles.searchTopTextContainer}>
          </View>
          <View>
            <Formik
              initialValues={initialValues}
              onSubmit={handleSubmitForm}
              validationSchema={validationSchema}
              >
              {({ handleChange, handleBlur, handleSubmit, values, isValid, dirty }) => (
                <View style={styles.searchFieldContainer}>
                  <View style={styles.form}>
                    <FieldInput style={styles.fieldInput}
                      handleChange={handleChange}
                      handleBlur={handleBlur}
                      value={values.phoneNumber}
                      fieldType="phoneNumber"
                      icon="phone"
                      placeholderText="49152901820"
                    />
                    <ErrorMessage
                      name="phoneNumber"
                      render={(msg) => (
                        <Text style={styles.errorText}>{msg}</Text>
                      )}
                    />
                  </View>
                  <View style={styles.buttonContainer}>
                  <Text>Abbrechen</Text>
                </Button>
                <Button
                  block
                  success
                  disabled={!isValid || !dirty}
                  onPress={handleSubmit}
                  style={styles.button}>
                  <Text>Speichern</Text>
                </Button>
                  </View>
                </View>
              )}
            </Formik>
          </View>
          {isSubmitted && showUsers(userData)}
        </View>
      </View>
    </SafeAreaView>
  );
};

Edit:

As suggested in comments, I tried using useFormik instead of but couldn’t make that work.

export const AddContactTry: React.FunctionComponent = () => {
  const { values, handleChange, handleSubmit, dirty, handleBlur, isValid}= useFormik({
    initialValues: {
      phoneNumber: '',
    },
    onSubmit: values => {
      handleSubmitForm(values);
    },
  });

  const [isSubmitted, setIsSubmitted] = useState(false);
  const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
  const navigation = useNavigation();
  const validationSchema = phoneNumberValidationSchema;

  const [
    createUserRelationMutation,
    {
      data: addingContactData,
      loading: addingContactLoading,
      error: addingContactError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted: () => {
      Alert.alert('Contact Added');
    },
  });

  const showUsers = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      if (data) {
        return (
          <View style={styles.users}>
            {data.users.nodes.map(
              (item: { firstName: string; lastName: string; id: number }) => {
                const userName = item.firstName
                  .concat(' ')
                  .concat(item.lastName);
                return (
                  <View style={styles.item} key={item.id}>
                    <Thumbnail
                      style={styles.thumbnail}
                      source={{
                        uri:
                          'https://cdn4.iconfinder.com/data/icons/avatars-xmas-giveaway/128/afro_woman_female_person-512.png',
                      }}></Thumbnail>
                    <Text style={styles.userName}>{userName}</Text>
                    <View style={styles.addButtonContainer}>
                      <Button
                        rounded
                        style={styles.addButton}
                        onPress={() => {
                          addContact(Number(item.id));
                          setIsSubmitted(false);
                          setUserData(null);
                        }}>
                        <Icon
                          name="plus"
                          size={moderateScale(20)}
                          color="black"
                        />
                      </Button>
                    </View>
                  </View>
                );
              },
            )}
          </View>
        );
      }
    },
    [createUserRelationMutation, userData],
  );

  const addContact = React.useCallback(
    (id: Number) => {
      console.log('Whats the Id', id);
      createUserRelationMutation({
        variables: {
          input: { relatedUserId: id, type: RelationType.Contact, userId: 30 },
        },
      });
    },
    [createUserRelationMutation],
  );

  const getContactId = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      if (data) {
        if (data.users.nodes.length == 0) {
          Alert.alert('No User Found');
        } else {
          setUserData(data);
        }
      }
    },
    [addContact],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getContactId,
    onError: _onLoadUserError,
  });

  const handleSubmitForm = React.useCallback(
    (values: FormValues) => {
      setIsSubmitted(true);
      const plusSign = '+';
      const newPhoneNumber = plusSign.concat(values.phoneNumber);
      console.log('Submitted');
      loadUsers({
        variables: {
          where: { phoneNumber: newPhoneNumber },
        },
      });
      values.phoneNumber = '';
    },
    [loadUsers],
  );

return (
    <SafeAreaView>
      <View style={styles.container}>
        <View style={styles.searchTopContainer}>
          <View style={styles.searchTopTextContainer}>
          </View>
          <View>
                <View style={styles.searchFieldContainer}>
                  <View style={styles.form}>
                    {/* <FieldInput style={styles.fieldInput}
                      handleChange={handleChange}
                      handleBlur={Formik.handleBlur}
                      value={Formik.values.phoneNumber}
                      fieldType="phoneNumber"
                      icon="phone"
                      placeholderText="49152901820"
                    /> */}
                     <Input style={styles.fieldInput}
                      onChangeText={handleChange('phoneNumber') as (text: string) => void}
                      onBlur={handleBlur('phoneNumber') as (event: any) => void}
                      value={values.phoneNumber}
                      //name="phoneNumber"
                      //fieldType="phoneNumber"
                      //icon="phone"
                      placeholder="49152901820"
                    />
                    <ErrorMessage
                      name="phoneNumber"
                      render={(msg) => (
                        <Text style={styles.errorText}>{msg}</Text>
                      )}
                    />
                  </View>
                  <View style={styles.buttonContainer}>
                <Button
                  block
                  success
                  disabled={!isValid || !dirty}
                  onPress={handleSubmit}
                  style={styles.button}>
                  <Text>Speichern</Text>
                </Button>
                  </View>
                </View>
          </View>
          {isSubmitted && showUsers(userData)}
        </View>
      </View>
    </SafeAreaView>
  );
};


Get this bounty!!!

#StackBounty: #reactjs #tags #react-dnd Does ReactTags work with React 16.12 applications?

Bounty: 50

I wanted to use ReactTags with my React 16.12 application following the instructions here — https://www.npmjs.com/package/react-tag-input . I installed react-dnd 11.1.1 . Below is my package.json file

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.4.0",
    "@testing-library/user-event": "^7.2.1",
    "bootstrap": "^4.4.1",
    "jquery": "^1.9.1",
    "react": "^16.12.0",
    "react-bootstrap": "^1.0.0-beta.17",
    "react-device-detect": "^1.12.1",
    "react-dnd": "^11.1.1",
    "react-dnd-html5-backend": "^11.1.1",
    "react-dom": "^16.12.0",
    "react-hamburger-menu": "^1.2.1",
    "react-native-flash-message": "^0.1.15",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.3.1",
    "react-tag-input": "^6.4.3",
    "typescript": "^3.8.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "NODE_ENV=development react-scripts build",
    "build:prod": "NODE_ENV=production react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "proxy": "http://localhost:8000",
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

I’m trying to implement the tags like so

import React from 'react';
import ReactDOM from 'react-dom';
import { WithContext as ReactTags } from 'react-tag-input';

const KeyCodes = {
  comma: 188,
  enter: 13,
};

const delimiters = [KeyCodes.comma, KeyCodes.enter];

class CoopTypes extends React.Component {
    constructor(props) {
        super(props);

        const tags = props.values.map(result => (
            {
                id: result.id,
                text: result.name
            }));
        this.state = {
            tags: tags,
            suggestions: props.values.map(result => ({
                id: result.id,
                text: result.name
            }))
        };
        this.handleDelete = props.handleDelete;
        this.handleAddition = props.handleAddition;
        this.handleDrag = this.handleDrag.bind(this);
    }

    handleDelete(i) {
        const { tags } = this.state;
        this.setState({
         tags: tags.filter((tag, index) => index !== i),
        });
    }

    handleAddition(tag) {
        this.setState(state => ({ tags: [...state.tags, tag] }));
    }

    handleDrag(tag, currPos, newPos) {
        const tags = [...this.state.tags];
        const newTags = tags.slice();

        newTags.splice(currPos, 1);
        newTags.splice(newPos, 0, tag);

        // re-render
        this.setState({ tags: newTags });
    }

    render() {
        const { tags, suggestions } = this.state;
        return (
            <div>
                <ReactTags tags={tags}
                    suggestions={suggestions}
                    handleDelete={this.handleDelete}
                    handleAddition={this.handleAddition}
                    handleDrag={this.handleDrag}
                    delimiters={delimiters} />
            </div>
        )
    }
};

export default CoopTypes;

but I’m running into the below error when I start up my app

TypeError: (0 , _reactDnd.DragDropContext) is not a function
./node_modules/react-tag-input/dist-modules/components/ReactTags.js
node_modules/react-tag-input/dist-modules/components/ReactTags.js:538
  535 | };
  536 | 
  537 | module.exports = {
> 538 |   WithContext: (0, _reactDnd.DragDropContext)(_reactDndHtml5Backend2.default)(ReactTags),
  539 |   WithOutContext: ReactTags,
  540 |   KEYS: _constants.KEYS
  541 | };
View compiled

Any thoughts on how to address this? Maybe the component doesn’t work anymore with newer React versions?


Get this bounty!!!

#StackBounty: #javascript #reactjs #redux Setting up half-icons with a rating system

Bounty: 50

I built a component that is basically a rating system that allows you to add more icons depending on the dropdown.

I was wondering if there was a way to make half stars, I’ve looked through older code on the internet, but there isn’t anything that has been updated. Any help with be appreciated

import React, { useState } from 'react'
import {FaStar} from "react-icons/all";
import './Rater.css'


const Rater = () => {
    const [rating, setRating] = useState(null)
    const [hover, setHover] = useState(null)
    const [value] = useState(100)
    const [iconValue, setIconValue] = useState(5)


    return (
        <div>
            <select onChange={(e) =>
            {setIconValue(Number(e.target.value))}}>
                { Array.from(new Array(value),(value, index) =>
                    index + 1).map(value => <option
                    key={value} value={value}>{value}</option>) }
            </select>
            <h1> Select Amount of Icons </h1>


            {[... Array(iconValue)].map((icon, i) => {
                const value = i + 1

                return (
                    <label>
                        <input type='radio'
                               name='rating'
                               value={value}
                               onClick={() => setRating(value)}
                        />
                        <FaStar classname='star'
                                color={value <= (hover || rating) ? '#ffc107' : '#e4e5e9'}
                                size={100}
                                onMouseEnter={() => setHover(value)}
                                onMouseLeave={() => setHover(null)}
                        />
                    </label>
                )
            })}
        </div>
    )
}

export default Rater


Get this bounty!!!

#StackBounty: #reactjs #webpack #storybook #react-proptypes How to enable prop-types in production for a React Storybook for the Docs a…

Bounty: 50

By default prop-types do not run in production for a react app. I realize this is a good thing to improve performance. However, we have a Storybook that we have built and are deploying it to a static site. Storybook has an addon called Docs that detects the prop-types for components and creates a table of the prop-types for easy to read documentation.

When running the storybook locally, everything works perfectly. The prop-types are detected and this table is generated.

SpinningLoader.propTypes = {
  color: PropTypes.string,
  size: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
};

enter image description here

However, since prop-types are disabled in production by default. They cannot be detected when the storybook is deployed to a static site.

enter image description here

Is there a way to enable prop-types in production? Or some other workaround?


Get this bounty!!!