Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
scratch-www
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
scratch-www
Commits
7a8f2b61
Unverified
Commit
7a8f2b61
authored
Apr 08, 2021
by
Paul Kaplan
Committed by
GitHub
Apr 08, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5231 from paulkaplan/use-getstate-in-thunks
Use getState in thunks instead of passing props around
parents
71bb3a76
bd279fe5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
78 additions
and
53 deletions
+78
-53
src/redux/comments.js
src/redux/comments.js
+3
-0
src/redux/studio-comment-actions.js
src/redux/studio-comment-actions.js
+17
-2
src/redux/studio.js
src/redux/studio.js
+30
-21
src/views/studio/studio-comments.jsx
src/views/studio/studio-comments.jsx
+7
-11
src/views/studio/studio-info.jsx
src/views/studio/studio-info.jsx
+13
-19
src/views/studio/studio.jsx
src/views/studio/studio.jsx
+8
-0
No files found.
src/redux/comments.js
View file @
7a8f2b61
...
...
@@ -186,3 +186,6 @@ module.exports.setMoreCommentsToLoad = moreCommentsToLoad => ({
module
.
exports
.
resetComments
=
()
=>
({
type
:
'
RESET_COMMENTS
'
});
// Selectors
module
.
exports
.
selectCommentCount
=
state
=>
state
.
comments
.
comments
.
length
;
src/redux/studio-comment-actions.js
View file @
7a8f2b61
...
...
@@ -18,9 +18,19 @@ const {
setError
,
setReplies
,
setRepliesDeleted
,
setRepliesRestored
setRepliesRestored
,
selectCommentCount
}
=
require
(
'
../redux/comments.js
'
);
const
{
selectIsAdmin
,
selectToken
}
=
require
(
'
./session
'
);
const
{
selectStudioId
}
=
require
(
'
./studio
'
);
const
getReplies
=
(
studioId
,
commentIds
,
offset
,
isAdmin
,
token
)
=>
(
dispatch
=>
{
dispatch
(
setFetchStatus
(
'
replies
'
,
Status
.
FETCHING
));
const
fetchedReplies
=
{};
...
...
@@ -50,8 +60,13 @@ const getReplies = (studioId, commentIds, offset, isAdmin, token) => (dispatch =
});
});
const
getTopLevelComments
=
(
id
,
offset
,
isAdmin
,
token
)
=>
(
dispatch
=>
{
const
getTopLevelComments
=
(
)
=>
((
dispatch
,
getState
)
=>
{
dispatch
(
setFetchStatus
(
'
comments
'
,
Status
.
FETCHING
));
const
state
=
getState
();
const
id
=
selectStudioId
(
state
);
const
offset
=
selectCommentCount
(
state
);
const
isAdmin
=
selectIsAdmin
(
state
);
const
token
=
selectToken
(
state
);
api
({
uri
:
`
${
isAdmin
?
'
/admin
'
:
''
}
/studios/
${
id
}
/comments`
,
authentication
:
token
?
token
:
null
,
...
...
src/redux/studio.js
View file @
7a8f2b61
...
...
@@ -3,7 +3,7 @@ const keyMirror = require('keymirror');
const
api
=
require
(
'
../lib/api
'
);
const
log
=
require
(
'
../lib/log
'
);
const
{
selectUserId
,
selectIsAdmin
,
selectIsSocial
}
=
require
(
'
./session
'
);
const
{
selectUserId
,
selectIsAdmin
,
selectIsSocial
,
selectUsername
,
selectToken
}
=
require
(
'
./session
'
);
const
Status
=
keyMirror
({
FETCHED
:
null
,
...
...
@@ -77,10 +77,31 @@ const setRoles = roles => ({
roles
:
roles
});
// Thunks
// Selectors
// Fine-grain selector helpers - not exported, use the higher level selectors below
const
isCreator
=
state
=>
selectUserId
(
state
)
===
state
.
studio
.
owner
;
const
isCurator
=
state
=>
state
.
studio
.
curator
;
const
isManager
=
state
=>
state
.
studio
.
manager
||
isCreator
(
state
);
// Action-based permissions selectors
const
selectCanEditInfo
=
state
=>
selectIsAdmin
(
state
)
||
isManager
(
state
);
const
selectCanAddProjects
=
state
=>
isManager
(
state
)
||
isCurator
(
state
)
||
(
selectIsSocial
(
state
)
&&
state
.
studio
.
openToAll
);
// This isn't "canComment" since they could be muted, but comment composer handles that
const
selectShowCommentComposer
=
state
=>
selectIsSocial
(
state
);
// Data selectors
const
selectStudioId
=
state
=>
state
.
studio
.
id
;
const
getInfo
=
studioId
=>
(
dispatch
=>
{
// Thunks
const
getInfo
=
()
=>
((
dispatch
,
getState
)
=>
{
dispatch
(
setFetchStatus
(
'
infoStatus
'
,
Status
.
FETCHING
));
const
studioId
=
selectStudioId
(
getState
());
api
({
uri
:
`/studios/
${
studioId
}
`
},
(
err
,
body
,
res
)
=>
{
if
(
err
||
typeof
body
===
'
undefined
'
||
res
.
statusCode
!==
200
)
{
dispatch
(
setFetchStatus
(
'
infoStatus
'
,
Status
.
ERROR
,
err
));
...
...
@@ -99,8 +120,12 @@ const getInfo = studioId => (dispatch => {
});
});
const
getRoles
=
(
studioId
,
username
,
token
)
=>
(
dispatch
=>
{
const
getRoles
=
(
)
=>
((
dispatch
,
getState
)
=>
{
dispatch
(
setFetchStatus
(
'
rolesStatus
'
,
Status
.
FETCHING
));
const
state
=
getState
();
const
studioId
=
selectStudioId
(
state
);
const
username
=
selectUsername
(
state
);
const
token
=
selectToken
(
state
);
api
({
uri
:
`/studios/
${
studioId
}
/users/
${
username
}
`
,
authentication
:
token
...
...
@@ -119,23 +144,6 @@ const getRoles = (studioId, username, token) => (dispatch => {
});
});
// Selectors
// Fine-grain selector helpers - not exported, use the higher level selectors below
const
isCreator
=
state
=>
selectUserId
(
state
)
===
state
.
studio
.
owner
;
const
isCurator
=
state
=>
state
.
studio
.
curator
;
const
isManager
=
state
=>
state
.
studio
.
manager
||
isCreator
(
state
);
// Action-based permissions selectors
const
selectCanEditInfo
=
state
=>
selectIsAdmin
(
state
)
||
isManager
(
state
);
const
selectCanAddProjects
=
state
=>
isManager
(
state
)
||
isCurator
(
state
)
||
(
selectIsSocial
(
state
)
&&
state
.
studio
.
openToAll
);
// This isn't "canComment" since they could be muted, but comment composer handles that
const
selectShowCommentComposer
=
state
=>
selectIsSocial
(
state
);
module
.
exports
=
{
getInitialState
,
studioReducer
,
...
...
@@ -146,6 +154,7 @@ module.exports = {
getRoles
,
// Selectors
selectStudioId
,
selectCanEditInfo
,
selectCanAddProjects
,
selectShowCommentComposer
...
...
src/views/studio/studio-comments.jsx
View file @
7a8f2b61
import
React
,
{
useEffect
,
useCallback
}
from
'
react
'
;
import
React
,
{
useEffect
}
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
useParams
}
from
'
react-router-dom
'
;
import
{
connect
}
from
'
react-redux
'
;
...
...
@@ -13,7 +13,7 @@ import {selectShowCommentComposer} from '../../redux/studio.js';
const
StudioComments
=
({
comments
,
getTopLevel
Comments
,
handleLoadMore
Comments
,
handleNewComment
,
moreCommentsToLoad
,
replies
,
...
...
@@ -21,13 +21,9 @@ const StudioComments = ({
})
=>
{
const
{
studioId
}
=
useParams
();
const
handleLoadComments
=
useCallback
(()
=>
{
getTopLevelComments
(
studioId
,
comments
.
length
);
},
[
studioId
,
comments
.
length
]);
useEffect
(()
=>
{
if
(
comments
.
length
===
0
)
getTopLevelComments
(
studioId
,
0
);
},
[
studioId
]);
if
(
comments
.
length
===
0
)
handleLoadMoreComments
(
);
},
[
]);
// Only runs once after the first render
return
(
<
div
>
...
...
@@ -58,7 +54,7 @@ const StudioComments = ({
{
moreCommentsToLoad
&&
<
Button
className=
"button load-more-button"
onClick=
{
handleLoadComments
}
onClick=
{
handleLoad
More
Comments
}
>
<
FormattedMessage
id=
"general.loadMore"
/>
</
Button
>
...
...
@@ -70,7 +66,7 @@ const StudioComments = ({
StudioComments
.
propTypes
=
{
comments
:
PropTypes
.
arrayOf
(
PropTypes
.
shape
({})),
getTopLevel
Comments
:
PropTypes
.
func
,
handleLoadMore
Comments
:
PropTypes
.
func
,
handleNewComment
:
PropTypes
.
func
,
moreCommentsToLoad
:
PropTypes
.
bool
,
replies
:
PropTypes
.
shape
({}),
...
...
@@ -86,7 +82,7 @@ export default connect(
shouldShowCommentComposer
:
selectShowCommentComposer
(
state
)
}),
{
getTopLevel
Comments
:
studioCommentActions
.
getTopLevelComments
,
handleLoadMore
Comments
:
studioCommentActions
.
getTopLevelComments
,
handleNewComment
:
studioCommentActions
.
addNewComment
}
)(
StudioComments
);
src/views/studio/studio-info.jsx
View file @
7a8f2b61
import
React
,
{
useEffect
}
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
useParams
}
from
'
react-router-dom
'
;
import
{
connect
}
from
'
react-redux
'
;
import
Debug
from
'
./debug.jsx
'
;
import
{
select
Username
,
selectToke
n
}
from
'
../../redux/session
'
;
import
{
select
IsLoggedI
n
}
from
'
../../redux/session
'
;
import
{
getInfo
,
getRoles
,
selectCanEditInfo
}
from
'
../../redux/studio
'
;
const
StudioInfo
=
({
username
,
studio
,
token
,
canEditInfo
,
onLoadInfo
,
onLoadRoles
})
=>
{
const
{
studioId
}
=
useParams
();
const
StudioInfo
=
({
isLoggedIn
,
studio
,
canEditInfo
,
onLoadInfo
,
onLoadRoles
})
=>
{
useEffect
(()
=>
{
// Load studio info after first render
if
(
studioId
)
onLoadInfo
(
studioId
);
},
[
studioId
]);
onLoadInfo
(
);
},
[]);
useEffect
(()
=>
{
// Load roles info once the user
name
is available
if
(
studioId
&&
username
&&
token
)
onLoadRoles
(
studioId
,
username
,
token
);
},
[
studioId
,
username
,
toke
n
]);
useEffect
(()
=>
{
// Load roles info once the user
is logged in
is available
if
(
isLoggedIn
)
onLoadRoles
(
);
},
[
isLoggedI
n
]);
return
(
<
div
>
...
...
@@ -35,8 +32,7 @@ const StudioInfo = ({username, studio, token, canEditInfo, onLoadInfo, onLoadRol
StudioInfo
.
propTypes
=
{
canEditInfo
:
PropTypes
.
bool
,
username
:
PropTypes
.
string
,
token
:
PropTypes
.
string
,
isLoggedIn
:
PropTypes
.
bool
,
studio
:
PropTypes
.
shape
({
// Fill this in as the data is used, just for demo now
}),
...
...
@@ -47,13 +43,11 @@ StudioInfo.propTypes = {
export
default
connect
(
state
=>
({
studio
:
state
.
studio
,
username
:
selectUsername
(
state
),
token
:
selectToken
(
state
),
isLoggedIn
:
selectIsLoggedIn
(
state
),
canEditInfo
:
selectCanEditInfo
(
state
)
}),
dispatch
=>
({
onLoadInfo
:
studioId
=>
dispatch
(
getInfo
(
studioId
)),
onLoadRoles
:
(
studioId
,
username
,
token
)
=>
dispatch
(
getRoles
(
studioId
,
username
,
token
))
})
{
onLoadInfo
:
getInfo
,
onLoadRoles
:
getRoles
}
)(
StudioInfo
);
src/views/studio/studio.jsx
View file @
7a8f2b61
...
...
@@ -78,5 +78,13 @@ render(
[
activity
.
key
]:
activity
.
reducer
,
studio
:
studioReducer
,
comments
:
commentsReducer
},
{
studio
:
{
// Include the studio id in the initial state to allow us
// to stop passing around the studio id in components
// when it is only needed for data fetching, not for rendering.
id
:
window
.
location
.
pathname
.
split
(
'
/
'
)[
2
]
}
}
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment