前提・実現したいこと
現在、フロントエンドにReact+Redux+Material-ui、バックエンドにLaravelを使用してレスポンシブルなWebサイトを開発しています。また、Chromeの検証ツールでiOSの動作確認を行なっています。
そこで、onClickイベントが検証ツールではしっかり反応するのですが、自前のiPhone(7 plus)をローカルに繋いで、動作確認をしたところ、onClickイベントが反応しません。フロントエンドだけで完結するonClickに関しては動作しますが、バックエンドのLaravel APIと通信するonClickだけが反応しません。
一応、自分なりに調べて、iPhoneはタッチイベントというものがあるらしいので、該当要素にCSSでcusor:pointerとスタイルしてみましたが、解決せず…。
下記に、一例のJWTログイン処理のソースコードを記述しています。
iOSでは一応ボタンは反応している様な気がするのですが、ログインすることができません。PCでは可能です。
どなたか解決方法のご教授お願いいたします。
追記
恐らくonClickは反応しているのですが、Laravel APIとの非同期通信がうまくいってないです。
上述している様に検証ツールでは動くのですが、iOSでは動きません。
該当のソースコード
JavaScript
1import React from 'react' 2import { withStyles } from '@material-ui/core/styles' 3import { Link } from 'react-router-dom' 4 5import { Redirect } from "react-router-dom" 6 7import { connect } from 'react-redux' 8import { bindActionCreators } from 'redux' 9import * as actions from '../../actions' 10 11import IconButton from '@material-ui/core/IconButton' 12import CloseIcon from '@material-ui/icons/Close' 13import Divider from '@material-ui/core/Divider' 14import Button from '@material-ui/core/Button' 15import Dialog from '@material-ui/core/Dialog' 16import DialogContent from '@material-ui/core/DialogContent' 17import DialogActions from '@material-ui/core/DialogActions' 18import { DialogContentText } from '@material-ui/core' 19import TextField from '@material-ui/core/TextField' 20import CircularProgress from '@material-ui/core/CircularProgress' 21 22const styles = () => ({ 23 root: { 24 display: 'flex', 25 justifyContent: 'center' 26 }, 27 title: { 28 display: 'flex', 29 justifyContent: 'center', 30 position: 'relative', 31 }, 32 loginTitle: { 33 marginTop: 20, 34 marginBottom: 10, 35 fontWeight: 'bold', 36 fontSize: 20 37 }, 38 close: { 39 position: 'absolute', 40 right: 3, 41 color: 'gray' 42 }, 43 input: { 44 width: '100%', 45 marginBottom: 20, 46 fontSize: 15 47 }, 48 loginButton: { 49 width: 200, 50 height: 50, 51 margin: 'auto', 52 marginTop: 10, 53 marginBottom: 30, 54 color: 'white', 55 fontSize: 15, 56 cursor: 'pointer' // 効果なし 57 }, 58 signupTitle: { 59 textAlign: 'center', 60 marginTop: 20, 61 marginBottom: 20, 62 fontWeight: 'bold', 63 fontSize: 20 64 }, 65 signupText: { 66 textAlign: 'center', 67 fontSize: 10 68 }, 69 signupButton: { 70 width: 200, 71 height: 50, 72 margin: 'auto', 73 marginBottom: 30, 74 color: 'white', 75 backgroundColor: '#bbb', 76 fontSize: 15 77 }, 78}) 79 80class LoginDialog extends React.Component { 81 constructor(props) { 82 super(props) 83 this.state = { 84 mail: '', 85 pass: '', 86 } 87 this.handleOnChange = this.handleOnChange.bind(this) 88 this.handleSubmit = this.handleSubmit.bind(this) 89 } 90 91 handleOnChange(e) { 92 this.setState({ 93 [e.target.name]: e.target.value, 94 }) 95 } 96 97 handleSubmit() { 98 const values = { 99 email: this.state.mail, 100 password: this.state.pass, 101 } 102 this.props.actions.loginUser(values, history) 103 } 104 105 render() { 106 const { classes } = this.props 107 108 const { LoginDialogReducer, AuthReducer, actions } = this.props 109 110 return ( 111 AuthReducer.isAuthenticated && localStorage.getItem('token') ? ( 112 <Redirect to={'/'} /> 113 ) : ( 114 <div className={classes.root}> 115 <Dialog 116 fullWidth={true} 117 open={LoginDialogReducer.loginDialogOpen} 118 onClose={actions.toggleLoginDialog} 119 aria-labelledby="alert-dialog-title" 120 aria-describedby="alert-dialog-description" 121 className={classes.content} 122 > 123 <div className={classes.title}> 124 <h6 className={classes.loginTitle}> 125 ログイン 126 </h6> 127 <IconButton 128 key="close" 129 aria-label="Close" 130 color="inherit" 131 className={classes.close} 132 onClick={actions.toggleLoginDialog} 133 > 134 <CloseIcon className={classes.icon} /> 135 </IconButton> 136 </div> 137 <DialogContent> 138 <TextField 139 required 140 label="名前" 141 name="mail" 142 className={classes.input} 143 onChange={e => this.handleOnChange(e)} 144 variant="outlined" 145 /> 146 <TextField 147 required 148 type="password" 149 label="パスワード" 150 name="pass" 151 className={classes.input} 152 onChange={e => this.handleOnChange(e)} 153 variant="outlined" 154 /> 155 </DialogContent> 156 <Button onClick={this.handleSubmit} variant="contained" color="primary" className={classes.loginButton}> 157 {this.props.AuthReducer.isRequesting ? <CircularProgress /> : 'ログイン'} 158 </Button> 159 <Divider variant="middle" /> 160 <DialogContent> 161 <h6 className={classes.signupTitle}> 162 初めてのお客様 163 </h6> 164 <DialogContentText className={classes.signupText}> 165 サービスを最大限利用するには会員登録が必要です 166 </DialogContentText> 167 </DialogContent> 168 <DialogActions> 169 <Button component={Link} to="/signup" onClick={actions.toggleLoginDialog} variant="contained" className={classes.signupButton}> 170 新規会員登録 171 </Button> 172 </DialogActions> 173 </Dialog> 174 </div> 175 ) 176 ) 177 } 178} 179 180const mapStateToProps = state => ({ 181 LoginDialogReducer: state.LoginDialogReducer, 182 AuthReducer: state.AuthReducer 183}) 184 185const mapDispatchToProps = dispatch => ({ 186 actions: bindActionCreators(actions, dispatch) // Actionを自動的にマッピング 187}) 188 189const StyledLoginDialog = withStyles(styles, { withTheme: true })(LoginDialog) 190 191export default connect(mapStateToProps, mapDispatchToProps)(StyledLoginDialog)
JavaScript
1// Jwt login 2export function loginUser({ email, password }) { 3 return async (dispatch) => { // 非同期処理 4 try { 5 // {hoge}でhoge:fugaと値が取れる 6 dispatch({ type: actionTypes.AUTH_REQUEST }) 7 const res = await axios.post(`${URL}/login`, { email, password }) 8 const datalist = { 9 'access_token': res.data.access_token, 10 'expiration_date': res.data.expiration_date 11 } 12 localStorage.setItem('token', JSON.stringify(datalist)) 13 localStorage.setItem('name', JSON.stringify(res.data.name)) 14 dispatch({ type: actionTypes.LOGIN_SUCCESS }) 15 } catch (error) { 16 console.log(error) 17 dispatch({ type: actionTypes.AUTH_FAILURE, }) 18 } 19 } 20}
JavaScript
1import * as actionTypes from '../utils/actionTypes' 2 3const initialState = { 4 loginDialogOpen: false, 5} 6 7const LoginDialogReducer = (state = initialState, action) => { 8 switch (action.type) { 9 case actionTypes.TOGGLE_LOGIN_DIALOG: 10 return Object.assign({}, state, { 11 loginDialogOpen: !state.loginDialogOpen 12 }) 13 default: 14 return state 15 } 16} 17 18export default LoginDialogReducer
試したこと
該当要素にCSSでcusor:pointerとスタイル
補足情報(FW/ツールのバージョンなど)
Laravel 5.8.*
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。