Search code examples
react-nativetagssetstate

How can I get SetState to stop overwriting my component tags


I am using these tags in my react native app: https://github.com/peterp/react-native-tags Being a react rookie I have a problem with SetState. I have set-up the tags like this:

<Tags
      initialText=""
      textInputProps={{
           placeholder: "Servicable Postcodes"
      }}
      initialTags={["3121"]}
      onChangeTags={(tags) => this.changeTags(tags)}
      inputStyle={{ backgroundColor: "white", borderBottomWidth: 1 }}
      renderTag={({ tag, index, onPress, deleteTagOnPress, readonly }) => (
           <TouchableOpacity key={${tag}-${index}} onPress={onPress}>
                <Text style={styles.tagStyle}>{tag}</Text>
           </TouchableOpacity>
      )}
 />

 changeTags(newtags) {
      //this.setState({ myTags: newtags.toString()});
      var tagList = newtags.toString();
      /*this.setState({myTags: tagList}, function () {
           console.log(this.state.myTags);
      });*/
  }

Adding tags works like this [3121] [1111] [2222]

So that code works well. As soon as I uncomment the setState it will run everything like normal but the tag will not get added to the list. So if I add 1111 my console log will be 3121, 1111 (But 1111 will not show as as a tag) then if i try to add another it will be 3121, 2222 etc.

I think because it re-renders with setState the tag is never added/overwritten and I just keep getting left with the single 3121 tag. Or maybe i'm a react noob and have no idea.

Any help is appreciated.

Thanks


Solution

  • You are right in saying that each render will cause the Tag component to reset back to 3121.

    To avoid this you need to store your current tags in your state like this:

    export default class App extends React.Component {
      state = { tags: ['3121'], myTags: "3121" }; // This line
    
      render() {
        return (
          <View style={styles.container}>
            <Tags
              initialText=""
              textInputProps={{
                placeholder: 'Servicable Postcodes',
              }}
              initialTags={this.state.tags} // This line
              onChangeTags={tags => this.changeTags(tags)}
              inputStyle={{ backgroundColor: 'white', borderBottomWidth: 1 }}
              renderTag={({ tag, index, onPress, deleteTagOnPress, readonly }) => (
                <TouchableOpacity key={`${tag}-${index}`} onPress={onPress}>
                  <Text style={styles.tagStyle}>{tag}</Text>
                </TouchableOpacity>
              )}
            />
          </View>
        );
      }
    
      changeTags(newtags) { // This function
        this.setState({ tags: newtags, myTags: newtags.toString() }, () =>
          console.log(this.state)
        );
      }
    }
    

    This means for each render (which will happen every time a tag is added as you are calling setState), the Tag component will render the tags you have stored in the state.

    I have also included another member in your state called myTags, which maps to the string value of your tags as it seems like this was necessary from your previous code.

    Here is a working snack