Alert.alert() 에 대한 질문이 있는데요

react-init

(shonee) #1

Alert.alert() 안에 타이틀 글을 넣고 타이틀 아래에 데이터를 표시하고 싶은데요

  • 오류가 떠서 어느부분이 문제인지 어떻게 해결해야 하는지 알려주시면 감사하겠습니다.

import React, { Component } from "react";
import {
TouchableOpacity,
Text,
View,
ListView,
TouchableHighlight,
Dimensions,
Image,
Animated,
StyleSheet,
TextInput,
ImageBackground,
Alert
} from "react-native";
import { SearchBar, ListItem, List } from "react-native-elements";
import Ionicons from "@expo/vector-icons/Ionicons";
import sitterdata from "../components/sitterdata";

const { width, height } = Dimensions.get("window");

/*
const datas = [
{
  name: "Registers",
  route: "Registers",
  icon: "phone-portrait",
  bg: "#C5F442"
},
{
  name: "PetSitters",
  route: "PetSitters",
  icon: "easel",
  bg: "#C5F442"
}
];
*/

export default class PetSitters extends Component {
constructor(props) {
  super(props);
  const ds = new ListView.DataSource({
    rowHasChanged: (r1, r2) => r1 !== r2
  });
  this.state = {
    dataSource: ds.cloneWithRows(sitterdata),
    refreshing: false
  };
}

static navigationOptions = ({ navigation }) => {
  return {
    title: "Pet Sitters",
    headerLeft: (
      <TouchableOpacity
        style={{ padding: 5, paddingRight: 15 }}
        //dataArray={datas}
        onPress={() => navigation.openDrawer()}
      >
        <Ionicons name={"ios-menu"} size={35} color={"#fff"} />
      </TouchableOpacity>
    ),

    headerRight: (
      <TouchableOpacity
        style={{ padding: 5, paddingRight: 15 }}
        onPress={() => navigation.navigate("Add")}
      >
        <Ionicons name={"ios-add"} size={35} color={"#fff"} />
      </TouchableOpacity>
    )
  };
};

showAlert(navigation) {
  Alert.alert(
    "이 펫시터와 거래 하시겠습니까?",
    this.state.dataSource(sitterdata.item.by),
    [
      {
        text: "Cancel",
        onPress: () => console.log("Cancel Pressed"),
        style: "cancel"
      },
      { text: "OK", onPress: () => navigation.navigate("Add") }
    ],
    { cancelable: false }
  );
}

async filterSearch(text) {
  const newData = sitterdata.filter(function(item) {
    const itemData = item.address.toUpperCase();
    const textData = text.toUpperCase();
    return itemData.indexOf(textData) > -1;
  });
  await this.setState({
    dataSource: this.state.dataSource.cloneWithRows(newData),
    text: text
  });
}

renderRow(rowData) {
  return (
    <TouchableHighlight style={styles.containerCell}>
      <View>
        <TouchableOpacity
          onPress={() => this.showAlert(this.props.navigation)}
        >
          <Image
            style={{ width: width, height: 180, resizeMode: "stretch" }}
            source={{ uri: rowData.image }}
          />
        </TouchableOpacity>
        <View style={styles.footerContainer}>
          <View style={styles.imageUser}>
            <Image
              style={styles.imageAvatar}
              source={{ uri: rowData.user }}
            />
          </View>
          <View style={styles.footerTextContainer}>
            <Text style={styles.text}>{rowData.introduce}</Text>
            <Text style={[styles.text, styles.textTitle]}>
              {rowData.address}
            </Text>
            <Text style={[styles.text, styles.textBy]}>By {rowData.by}</Text>
          </View>
        </View>
      </View>
    </TouchableHighlight>
  );
}

render() {
  return (
    <View style={styles.container}>
      <Animated.View
        style={[
          styles.content,
          {
            width: width,
            backgroundColor: "#dfe4ea",
            flex: 1,
            transform: [
              {
                perspective: 450
              }
            ]
          }
        ]}
      >
        <SearchBar
          onChangeText={text => this.filterSearch(text)}
          placeholder={"여기에 입력하세요"}
          value={this.state.text}
          lightTheme
          containerStyle={{}}
        />
        <ListView
          enableEmptySections={true}
          style={styles.listContainer}
          renderRow={this.renderRow.bind(this)}
          dataSource={this.state.dataSource}
        />
      </Animated.View>
    </View>
  );
}
}

위에는 전체 코드이구요 제가 오류가 나는부분은 Alert.alert() 부분입니다.

showAlert(navigation) {
  Alert.alert(
    "이 펫시터와 거래 하시겠습니까?",
    this.state.dataSource(sitterdata.item.by),
    [
      {
        text: "Cancel",
        onPress: () => console.log("Cancel Pressed"),
        style: "cancel"
      },
      { text: "OK", onPress: () => navigation.navigate("Add") }
    ],
    { cancelable: false }
  );
}

이부분에서 오류가 나는데요

    this.state.dataSource(sitterdata.item.by),

(이종은(Jong Lee)) #2

일단 에러는 undefined의 속성에 접근하려고 했을 때 문제입니다. 자바스크립트는 undefined의 속성에 접근하면 에러가 납니다. this.sate.sitterdata가 undefeined라는 얘기입니다. 지난 번에도 이 undefined is not an object 에러로 질문 하셨던 것 같은데 이 에러는 자바스크립트에서 가장 흔히 접하게 되는 에러중에 하나이다보니 이에 명확히 이해하고 넘어가시길 바랍니다.

그리고 ListView는 공식 문서에 나와있듯이 Deprecated된 컴포넌트입니다. 이를 사용하기 보다는 FlatList나 SectionList등을 사용하세요.


(shonee) #3
export default class PetSitters extends Component {
  constructor(props) {
    super(props);
    const ds = new FlatList.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    });
    this.state = {
      dataSource: ds.cloneWithRows(sitterdata),
      refreshing: false
    };
  }

 render() {
    return (
      <View style={styles.container}>
        <Animated.View
          style={[
            styles.content,
            {
              width: width,
              backgroundColor: "#dfe4ea",
              flex: 1,
              transform: [
                {
                  perspective: 450
                }
              ]
            }
          ]}
        >
          <SearchBar
            onChangeText={text => this.filterSearch(text)}
            placeholder={"여기에 입력하세요"}
            value={this.state.text}
            lightTheme
            containerStyle={{}}
          />
          <FlatList
            enableEmptySections={true}
            style={styles.listContainer}
            renderRow={this.renderRow.bind(this)}
            dataSource={this.state.dataSource}
          />
        </Animated.View>
      </View>

#기존 ListView 에 있던 것을 FlatList로 바꿨는데요.

타입 자체가 에러라고 하는데…형식이 아예 달라서 그런건가요?


(이종은(Jong Lee)) #4

사용법이 다릅니다. FlatList 문서를 살펴보세요. 무언가 안될 때는 최 우선적으로 해당 컴포넌트의 공식 문서에 나와있는 설명과 예제를 살펴보세요. 많은 문제를 스스로 해결 할 수 있을 겁니다.


(shonee) #5
import React, { Component } from "react";
import {
  TouchableOpacity,
  Text,
  View,
  ListView,
  TouchableHighlight,
  Dimensions,
  Image,
  Animated,
  StyleSheet,
  TextInput,
  ImageBackground,
  Alert,
  FlatList
} from "react-native";
import { SearchBar, ListItem, List } from "react-native-elements";
import Ionicons from "@expo/vector-icons/Ionicons";
import sitterdata from "../components/sitterdata";

const { width, height } = Dimensions.get("window");

/*
const datas = [
  {
    name: "Registers",
    route: "Registers",
    icon: "phone-portrait",
    bg: "#C5F442"
  },
  {
    name: "PetSitters",
    route: "PetSitters",
    icon: "easel",
    bg: "#C5F442"
  }
];
*/

export default class PetSitters extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: sitterdata,
      refreshing: false
    };
  }

  static navigationOptions = ({ navigation }) => {
    return {
      title: "Pet Sitters",
      headerLeft: (
        <TouchableOpacity
          style={{ padding: 5, paddingRight: 15 }}
          //dataArray={datas}
          onPress={() => navigation.openDrawer()}
        >
          <Ionicons name={"ios-menu"} size={35} color={"#fff"} />
        </TouchableOpacity>
      ),

      headerRight: (
        <TouchableOpacity
          style={{ padding: 5, paddingRight: 15 }}
          onPress={() => navigation.navigate("Add")}
        >
          <Ionicons name={"ios-add"} size={35} color={"#fff"} />
        </TouchableOpacity>
      )
    };
  };

  showAlert(navigation) {
    Alert.alert(
      "이 펫시터와 거래 하시겠습니까?",
      // this.item.bind(sitterdata.by),
      //"데이터 입력",
      this.state.data(sitterdata.by),
      [
        {
          text: "Cancel",
          onPress: () => console.log("Cancel Pressed"),
          style: "cancel"
        },
        { text: "OK", onPress: () => navigation.navigate("Add") }
      ],
      { cancelable: false }
    );
  }

  async filterSearch(text) {
    const newData = sitterdata.filter(function(item) {
      const itemData = item.address.toUpperCase();
      const textData = text.toUpperCase();
      return itemData.indexOf(textData) > -1;
    });
    await this.setState({
      data: newData,
      text: text
    });
  }

  refreshData = () => {};

  renderItem = ({ item }) => {
    return (
      <TouchableHighlight style={styles.containerCell}>
        <View>
          <TouchableOpacity
            onPress={() => this.showAlert(this.props.navigation)}
          >
            <Image
              style={{
                width: width,
                height: 180,
                resizeMode: "stretch"
              }}
              source={{ uri: item.image }}
            />
          </TouchableOpacity>
          <View style={styles.footerContainer}>
            <View style={styles.imageUser}>
              <Image style={styles.imageAvatar} source={{ uri: item.user }} />
            </View>
            <View style={styles.footerTextContainer}>
              <Text style={styles.text}>{item.introduce}</Text>
              <Text style={[styles.text, styles.textTitle]}>
                {item.address}
              </Text>
              <Text style={[styles.text, styles.textBy]}>By {item.by}</Text>
            </View>
          </View>
        </View>
      </TouchableHighlight>
    );
  };

  render() {
    return (
      <View style={styles.container}>
        <Animated.View
          style={[
            styles.content,
            {
              width: width,
              backgroundColor: "#dfe4ea",
              flex: 1,
              transform: [
                {
                  perspective: 450
                }
              ]
            }
          ]}
        >
          <SearchBar
            onChangeText={text => this.filterSearch(text)}
            placeholder={"여기에 입력하세요"}
            value={this.state.text}
            lightTheme
            containerStyle={{}}
          />
          <FlatList
            style={styles.listContainer}
            onRefresh={this.refreshData}
            renderItem={this.renderItem}
            refreshing={this.state.refreshing}
            data={this.state.data}
            keyExtractor={(item, index) => item.address}
          />
        </Animated.View>
      </View>
    );
  }
}

export class AddPetScreen extends Component {
  static navigationOptions = ({ navigation }) => {
    const params = navigation.state.params || {};

    return {
      title: "Add Pet"
    };
  };

  render() {
    return (
      <View style={styles.container2}>
        <View style={{ alignItems: "center", paddingBottom: 50 }}>
          <ImageBackground
            style={{
              width: "100%",
              height: 200,
              justifyContent: "center",
              alignItems: "center",
              backgroundColor: "#fff"
            }}
            source={require("../image/car.png")}
            imageStyle={{ opacity: 0.3 }}
          >
            <Text
              style={{
                fontSize: 30,
                color: "black",
                fontWeight: "bold"
              }}
            >
              차량을 추가해주세요
            </Text>
          </ImageBackground>
        </View>
        <View
          style={{ flexDirection: "row", alignItems: "center", padding: 5 }}
        >
          <Text
            style={{
              fontSize: 18,
              justifyContent: "center",
              alignItems: "center",
              width: "20%",
              color: "#fff"
            }}
          >
            Vin:
          </Text>
          <TextInput
            secureTextEntry={true}
            style={{
              backgroundColor: "#fff",
              borderColor: "#fff",
              borderRadius: 15,
              borderWidth: 2,
              height: 40,
              width: "70%",
              paddingHorizontal: 10
            }}
            placeholder="Vin 넘버를 입력하세요"
          />
        </View>
        <View
          style={{ flexDirection: "row", alignItems: "center", padding: 5 }}
        >
          <Text
            style={{
              fontSize: 18,
              justifyContent: "center",
              alignItems: "center",
              width: "20%",
              color: "#fff"
            }}
          >
            Model:
          </Text>
          <TextInput
            secureTextEntry={true}
            style={{
              backgroundColor: "#fff",
              borderColor: "#fff",
              borderRadius: 15,
              borderWidth: 2,
              height: 40,
              width: "70%",
              paddingHorizontal: 10
            }}
            placeholder="Model명를 입력하세요"
          />
        </View>
        <View
          style={{ flexDirection: "row", alignItems: "center", padding: 5 }}
        >
          <Text
            style={{
              fontSize: 18,
              justifyContent: "center",
              alignItems: "center",
              width: "20%",
              color: "#fff"
            }}
          >
            차량회사:
          </Text>
          <TextInput
            secureTextEntry={true}
            style={{
              backgroundColor: "#fff",
              borderColor: "#fff",
              borderRadius: 15,
              borderWidth: 2,
              height: 40,
              width: "70%",
              paddingHorizontal: 10
            }}
            placeholder="차량 회사명을 입력하세요"
          />
        </View>
        <View
          style={{ flexDirection: "row", alignItems: "center", padding: 5 }}
        >
          <Text
            style={{
              fontSize: 18,
              justifyContent: "center",
              alignItems: "center",
              width: "20%",
              color: "#fff"
            }}
          >
            year:
          </Text>
          <TextInput
            secureTextEntry={true}
            style={{
              backgroundColor: "#fff",
              borderColor: "#fff",
              borderRadius: 15,
              borderWidth: 2,
              height: 40,
              width: "70%",
              paddingHorizontal: 10
            }}
            placeholder="차량 연식을 입력하세요"
            keyboardType="number-pad"
          />
        </View>
        <View
          style={{ flexDirection: "row", alignItems: "center", padding: 5 }}
        >
          <Text
            style={{
              fontSize: 18,
              justifyContent: "center",
              alignItems: "center",
              width: "20%",
              color: "#fff"
            }}
          >
            image:
          </Text>
          <TouchableOpacity
            style={[
              {
                width: "10%",
                height: 30,
                borderColor: "#fff",
                borderWidth: 1,
                borderRadius: 10,
                alignItems: "center",
                justifyContent: "center",
                backgroundColor: "#fff"
              }
            ]}
            onPress={() => {}}
          >
            <Ionicons name={"ios-add"} size={35} color={"gray"} />
          </TouchableOpacity>
        </View>
        <View style={{ alignItems: "center", padding: 5 }}>
          <TouchableOpacity
            style={{
              width: "100%",
              height: 30,
              borderColor: "#fff",
              borderWidth: 1,
              borderRadius: 10,
              alignItems: "center",
              justifyContent: "center",
              backgroundColor: "#74b9ff"
            }}
            onPress={() => {}}
          >
            <Text style={{ fontSize: 17, color: "#fff" }}> 차량 추가</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container2: {
    flex: 1,
    backgroundColor: "#74b9ff",
    justifyContent: "center"
  },
  container: {
    flex: 1,
    backgroundColor: "red",
    justifyContent: "center"
  },
  textInput: {
    height: 30,
    borderWidth: 5,
    borderColor: "red",
    marginTop: 50,
    marginHorizontal: 10
  },
  content: {
    zIndex: 1
  },
  footerContainer: {
    flexDirection: "row",
    paddingHorizontal: 10,
    paddingVertical: 10,
    backgroundColor: "#555566"
  },
  imageAvatar: {
    width: 50,
    height: 50,
    borderRadius: 25,
    marginRight: 5
  },
  listContainer: {
    marginHorizontal: 10
  },
  text: {
    color: "#fff"
  },
  containerCell: {
    marginBottom: 10
  },
  textTitle: {
    fontSize: 13
  },
  textBy: {
    fontSize: 12
  },
  textMenu: {
    fontSize: 20,
    color: "#fff"
  }
});

#기존 ListView 에서 FlatList로 바꾸었는데요

 constructor(props) {
    super(props);
    this.state = {
      data: sitterdata,
      refreshing: false,
      text: sitterdata[0].by
    };
  }
showAlert(navigation) {
    Alert.alert(
      "이 펫시터와 거래 하시겠습니까?",
      // this.item.bind(sitterdata.by),
      //"데이터 입력",
      this.state.text,

      [
        {
          text: "Cancel",
          onPress: () => console.log("Cancel Pressed"),
          style: "cancel"
        },
        { text: "OK", onPress: () => navigation.navigate("Add") }
      ],
      { cancelable: false }
    );
  }

이부분에서 클릭시에 this.state.text가 작동하는건 보았는데요

  • 클릭할때 마다 그림 내용에 맞는 by값을 표현하려면 어떻게 해야되나요?