Bonjour,
Je rencontre un soucis, dans mon application j'ai 3 niveaux de composants.
- Collection
- Tableau
- Bouton
Lorsque je clique sur mon bouton j'ai bien ma saga qui est appelé et l'appel ajax s'effectue correctement. Par contre je dois appuyé deux fois sur mon bouton pour que la ligne et le bouton en question se mette à jour sur l'affichage.
Quand je regarde l'évolution de mon state je vois bien le changement de donnée.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 class MyCollection extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } componentDidMount() { this.props.filterSearchList([]); } handleSubmit(event) { event.preventDefault(); const data = new FormData(event.target); this.props.filterSearchList(data); } addBook(book) { this.props.bookAdd(book.id); } render() { return ( <div> <ContainerHeader match={this.props.match} title={<IntlMessages id="pages.myCollection" />} /> <div className="row"> <div className="col-12"> <form onSubmit={this.handleSubmit} className="jr-card pt-0"> <FormControl className="w-100 mb-2"> <TextField id="searchText" label={<IntlMessages id="common.search" />} name="searchText" /> </FormControl> </form> </div> </div> <BookListTable list={this.props.list} addBookCallBack={this.addBook.bind(this)} /> {/* <BookListCard list={this.props.list} /> */} </div> ); } } const mapStateToProps = state => ({ list: state.list, book: state.book, }); const mapDispatchToProps = dispatch => ( bindActionCreators({ filterSearchList, bookAdd }, dispatch) ); export default connect(mapStateToProps, mapDispatchToProps)(MyCollection);
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 class BookListTable extends Component { constructor(props) { super(props); this.state = { page: 0, rowsPerPage: 5, }; } handleChangePage = (event, page) => { this.setState({page}); }; handleChangeRowsPerPage = (event) => { this.setState({rowsPerPage: event.target.value}); }; addBook(book) { this.props.addBookCallBack(book); } render() { const {classes, list} = this.props; const {rowsPerPage, page} = this.state; const emptyRows = rowsPerPage - Math.min(rowsPerPage, list.length - (page * rowsPerPage)); return ( <div className="row"> <CardBox styleName="col-lg-12" cardStyle="p-0"> <div className={classes.tableWrapper}> <Table className={classes.table}> <TableBody> {list.slice(page * rowsPerPage, (page * rowsPerPage) + rowsPerPage).map(n => ( <TableRow key={n.id}> <TableCell> <div className="user-profile d-flex flex-row align-items-center"> <Avatar alt={n.title} src={n.image} className="ml-3 user-avatar" /> <div className="user-detail"> <h5 className="user-name">{n.title} - {n.author} - {n.isbn}</h5> <p className="user-description">{n.tags}</p> </div> </div> </TableCell> <TableCell>{n.addDate}</TableCell> <TableCell className={classes.tableCell}> <AddRemoveBook className="mr-2" bookId={n.id} bookInfos={n} addBookCallBack={this.addBook.bind(this)} /> <UpdateBook className="mr-2" /> <ReportBook className="mr-2" /> </TableCell> </TableRow> ))} {emptyRows > 0 && ( <TableRow style={{height: 48 * emptyRows}}> <TableCell colSpan={6} /> </TableRow> )} </TableBody> <TableFooter> <TableRow> <TablePagination colSpan={3} count={list.length} rowsPerPage={rowsPerPage} page={page} onChangePage={this.handleChangePage} onChangeRowsPerPage={this.handleChangeRowsPerPage} ActionsComponent={TablePaginationActionsWrapped} labelRowsPerPage={<IntlMessages id="common.bookPerPage" />} labelDisplayedRows={({ from, to, count }) => <IntlMessages id="common.labelDisplayedRows" values={{ from, to, count }} />} /> </TableRow> </TableFooter> </Table> </div> </CardBox> </div> ); } } BookListTable.propTypes = { classes: PropTypes.object.isRequired, }; export default withStyles(styles)(BookListTable);
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 class AddRemoveBook extends React.PureComponent { constructor(props) { super(props); this.state = { bookInfos: props.bookInfos, open: false, }; this.handleClick = this.handleClick.bind(this); } handleClickOpen = () => { this.setState({open: true}); }; handleRequestClose = () => { this.setState({open: false}); }; handleClick(event) { event.preventDefault(); this.props.addBookCallBack(this.state.bookInfos); } renderAdd(className) { return ( <Tooltip title={<IntlMessages id="common.addToCollection" />} > <Button variant="fab" className={`jr-fab-btn jr-btn-fab-xs bg-green text-white ${className}`} onClick={this.handleClick} > <i className="zmdi zmdi-plus zmdi-hc-fw" /> </Button> </Tooltip> ); } renderRemove(className) { return ( <span> <Tooltip title={<IntlMessages id="common.removeFromCollection" />} > <Button variant="fab" className={`jr-fab-btn jr-btn-fab-xs bg-grey text-white ${className}`} onClick={this.handleClickOpen} > <i className="zmdi zmdi-delete zmdi-hc-fw" /> </Button> </Tooltip> <Dialog open={this.state.open} onClose={this.handleRequestClose}> <DialogContent> <DialogContentText> <IntlMessages id="common.removeAlertQuestion" /> </DialogContentText> </DialogContent> <DialogActions> <Button onClick={this.handleRequestClose} className="jr-btn jr-btn bg-red text-white" > <IntlMessages id="common.cancel" /> </Button> <Button onClick={this.handleRequestClose} className="jr-btn jr-btn bg-green text-white" > <IntlMessages id="common.confirm" /> </Button> </DialogActions> </Dialog> </span> ); } render() { const {className, bookInfos} = this.props; return ( <span> {bookInfos.inCollection && this.renderAdd(className)} {!bookInfos.inCollection && this.renderRemove(className)} </span> ); } } export default AddRemoveBook;
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import { LIST_SEARCH_FILTER, LIST_SEARCH_FILTER_SUCCESS, LIST_UPDATE_IN_COLLECTION } from 'constants/ActionTypes'; export default (state = [], action) => { switch (action.type) { case LIST_SEARCH_FILTER: { return state; } case LIST_SEARCH_FILTER_SUCCESS: { return action.payload; } case LIST_UPDATE_IN_COLLECTION: { const index = state.findIndex(book => book.id === action.payload.id); state[index] = action.payload; return state; } default: return state; } };
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import { BOOK_ADD_SUCCESS } from 'constants/ActionTypes'; export default (state = [], action) => { switch (action.type) { case BOOK_ADD_SUCCESS: { return action.payload; } default: return state; } };
De ce que je comprends le soucis vient du fait que le changement de state se fait de manière asynchrone mais je vois pas comment procéder pour lui dire de se mettre à jour au moment ou le state est réellement à jour.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 import axios from 'axios'; import {all, call, fork, put, takeEvery} from 'redux-saga/effects'; import { BOOK_ADD, } from 'constants/ActionTypes'; import {bookAddSuccess} from 'actions/Book'; import {updateBookInList} from 'actions/List'; let counter = 0; function createData(title, author, image, addDate, tags, isbn, inCollection) { counter += 1; return {id: counter, title, author, image, addDate, tags, isbn, inCollection}; } function* add(action) { try { const result = yield call(action => axios.get( 'https://my-json-server.typicode.com/typicode/demo/posts' ) .then((res) => { counter = 0; return createData('Sans Application', 'Renewal', 'http://via.placeholder.com/150x150', '6:06', '$54.20', 'ISBN', false); }) .catch((err) => { throw err; }) , action); yield put(bookAddSuccess(result)); yield put(updateBookInList(result)); } catch (error) { console.log(error); } } export function* addToCollection() { yield takeEvery(BOOK_ADD, add); } export default function* rootSaga() { yield all( [ fork(addToCollection) ] ); }