Kanwarjeet Singh
Kanwarjeet Singh

Reputation: 745

Adding new object to an array in React Native

I have created a form to upload the image and text field on the home screen but I am facing a problem that it's not updating the array and validation is failing due to that. I think something wrong with my implementation

AddPost.js

const validationSchema = Yup.object({
  title: Yup.string().required().min(5).max(15).label("Title"),
  des: Yup.string().required().min(15).max(200).label("Description"),
  image: Yup.array().required().label("Image"),
});

class AddPost extends Component {
  render() {
    return (
      <Formik
        initialValues={{ title: "", des: "", image: [] }}
        onSubmit={(values, actions) => {
          actions.resetForm();
          this.props.addPost(values);
        }}
        validationSchema={validationSchema}
      >
        {(value) => (
          <View>
            <FormImage />
            <Text style={styles.error}>
              {value.touched.image && value.errors.image}
            </Text>
            <TextInput
              placeholder="Title"
              onChangeText={value.handleChange("title")}
              style={styles.input}
              value={value.values.title}
              onBlur={value.handleBlur("title")}
            />
            <Text style={styles.error}>
              {value.touched.title && value.errors.title}
            </Text>

Here is my form field I think everything is right here

home.js

class Home extends Component {
  state = {
    modal: false,
    post: [
      {
        key: "1",
        title: "A Good Boi",
        des: "He's a good boi and every one know it.",
        image: require("../assets/dog.jpg"),
      },
      {
        key: "2",
        title: "John Cena",
        des: "As you can see, You can't see me!",
        image: require("../assets/cena.jpg"),
      },
    ],
    image: null,
  };


  addPost = (posts) => {
    posts.key = Math.random().toString();
    this.setState.post((currentPost) => {
      return [posts, ...currentPost];
    });
    this.state.modal();
  };

  render() {
    return (
      <Screen style={styles.screen}>
        <Modal visible={this.state.modal} animationType="slide">
          <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
            <View style={styles.modalContainer}>
              <AddPost addPost={() => this.addPost} />
            </View>
          </TouchableWithoutFeedback>
        </Modal>
        <FlatList
          data={this.state.post}
          renderItem={({ item }) => (
            <>
              <Card
                title={item.title}
                subTitle={item.des}
                image={item.image}
                onPress={() => this.props.navigation.navigate("Edit", item)}
              />
            </>

I think something wrong with the addPost method because I did it before with function base that time I only added text to the list and its worked but in class base I don't know to do it I just try the same way I did in function base

FormImage.js

class FormImage extends Component {
  state = {
    image: null,
    hasCameraPermission: null,
  };

  async componentDidMount() {
    const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
    this.setState({ hasCameraPermission: status === "granted" });
  }

  _pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: true,
      aspect: [4, 3],
    });

    if (!result.cancelled) {
      this.setState({ image: result.uri });
    }
  };

  render() {
    const { image } = this.state;
    return (
      <TouchableWithoutFeedback onPress={this._pickImage}>
        <View style={styles.container}>
          {!image && (
            <MaterialCommunityIcons
              color={colors.medium}
              name="camera"
              size={40}
            />
          )}
          {image && <Image style={styles.image} source={{ uri: image }} />}
        </View>
      </TouchableWithoutFeedback>
    );
  }
}


after submiting enter image description here

Upvotes: 0

Views: 991

Answers (2)

You are not updating images to formik so is normal you get the required error. First in your AddPost Component pass down formikProps to FormImage component.

return (
      <Formik
        initialValues={{ title: "", des: "", image: [] }}
        onSubmit={(values, actions) => {
          // actions.resetForm(); --> comment this
          this.props.addPost(values);
        }}
        validationSchema={validationSchema}
      >
        {(value) => (
          <View>
            <FormImage formikProps={value}/>
            <Text style={styles.error}>
              {value.touched.image && value.errors.image}
            </Text>
            <TextInput
              placeholder="Title"
              onChangeText={value.handleChange("title")}
              style={styles.input}
              value={value.values.title}
              onBlur={value.handleBlur("title")}
            />
            <Text style={styles.error}>
              {value.touched.title && value.errors.title}
            </Text>

In FormImage use that formikProps and call setFieldValue("image", result.uri) to update formik value for image.

class FormImage extends Component {
  state = {
    image: null,
    hasCameraPermission: null,
  };

  async componentDidMount() {
    const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
    this.setState({ hasCameraPermission: status === "granted" });
  }

  _pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: true,
      aspect: [4, 3],
    });

    if (!result.cancelled) {
      this.setState({ image: result.uri });
      this.props.formikProps.setFieldValue("image", result.uri);
    }
  };

  render() {
    const { image } = this.state;
    return (
      <TouchableWithoutFeedback onPress={this._pickImage}>
        <View style={styles.container}>
          {!image && (
            <MaterialCommunityIcons
              color={colors.medium}
              name="camera"
              size={40}
            />
          )}
          {image && <Image style={styles.image} source={{ uri: image }} />}
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

In home

addPost = (posts) => {
    console.log('add post');
    posts.key = Math.random().toString();
    this.setState((prevState) => {
      return {...prevState, post: [...prevState.post, ...posts], modal: 
      true };
    });
    // this.state.modal();
  };

Upvotes: 0

Sarun UK
Sarun UK

Reputation: 6766

Iam assuming your addPost function logic is wrong,

Try the below code

 addPost = (posts) => {
    posts.key = Math.random().toString();
    this.setState((prevState) => {
      return {...prevState, post: [...prevState.post, ...posts] };
    });
    this.state.modal();
  };

Let me know incase you are getting the same error.

Upvotes: 1

Related Questions