I am confused with reactjs api json call back.
In my container>> i have an api response from this --> let broadcast = this.props.broadcastDetailsPageApiResponse;
I need to map the values to 'broadcastData' variable to print it in component page html.(fileds like 'channel','description','recordedUrl',
How can i do it?
The api response as follows.
broadcastdetailcontainer.jsx: place to map console.log("need to map");line no 34.
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux';
import BroadcastDetailPage from '../components/broadcastList/broadcastDetailPage.jsx'
import * as detailPageActions from '../actions/detailPageActions.jsx'
class BroadcastDetailContainer extends Component {
constructor(props) {
super(props);
this.state = {broadcastData: {}};
this.updateBroadcastData = this.updateBroadcastData.bind(this);
}
componentDidMount() {
let broadcastId = this.props.params.broadcastId;
console.log("Broadcast Id in the componentDidMount: " + broadcastId);
this.updateBroadcastData(broadcastId);
}
updateBroadcastData(broadcastId) {
let broadcastData;
let broadcast = this.props.broadcastDetailsPageApiResponse;
// console.log("broadcast: " + JSON.stringify(broadcast));
if (broadcast != null) {
/////////////////////////////////////////////////////////////////
broadcastData = broadcast.channel;
broadcastData = broadcast.user;
console.log("need to map");
//console.log(broadcastData);
/////////////////////////////////////////////////////////////////
}
let content = this.props.homePageApiResponse.content;
if (content != null & broadcastData == null) {
console.log('entered when the home API');
for (let i = 0; i < content.length; i++) {
if (content[i].id == broadcastId) {
broadcastData = content[i];
break;
}
}
}
if (broadcastData == null) {
content = this.props.searchPageApiResponse.content;
if (content != null) {
console.log('entered when the search API');
for (let i = 0; i < content.length; i++) {
if (content[i].id == broadcastId) {
broadcastData = content[i];
console.log(broadcastData);
break;
}
}
}
}
if (broadcastData == null) {
this.props.actions.callDetailApi(broadcastId);
}
else{
this.setState({broadcastData: broadcastData});
}
}
componentWillReceiveProps(nextProps) {
let broadcastId = nextProps.params.broadcastId;
console.log('componentWillReceiveProps');
this.updateBroadcastData(broadcastId);
}
render() {
//console.log("rendered: "+JSON.stringify(this.props.broadcastDetailsPageApiResponse));
return (
<div>
{this.state.broadcastData &&
<BroadcastDetailPage
broadcastDetail={this.state.broadcastData}/>
}
</div>
)
}
}
const mapStateToProps = (state) => ({
homePageApiResponse: state.homePageApiResponse,
searchPageApiResponse: state.searchPageApiResponse,
broadcastDetailsPageApiResponse: state.detailPageApiResponse,
})
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(detailPageActions, dispatch)
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)
(BroadcastDetailContainer)
I need to display the map values in the following component page:
import React, {Component} from "React";
import {Row, Clearfix} from "react-bootstrap/lib";
import VideoPlayer from "./videoPlayer.jsx";
class BroadcastDetailPage extends Component {
render() {
let broadcastData = this.props.broadcastDetail;
return (
<Row>
<div className="popup-cont-container">
<VideoPlayer broadcastData={broadcastData}/>
<div className="video-info">
<div className="info-left">
<div className="main-tag">
# {broadcastData.channel}
</div>
<div className="datenTime">
On Date
</div>
<div className="datenTime"> Location
</div>
<div className="video-info-main"> </div>
<div className="at">#
{broadcastData.handle} </div>
</div>
<div className="info-right">
<span><img src="images/eyeico.png"/>
<a> </a> Live viewers
</span>
<span><img src="images/heart.png"/>
<a> </a> Likes
</span>
</div>
</div>
<Clearfix/>
</div>
</Row>
);
}
}
export default BroadcastDetailPage
{"id":4,"user":{"userId":1,"chatUserId":0,"handle":"satishkrypto","countryCode":"+971","phone":"569942359","picUrl":"https://ss-ap-southeast-1.amazonaws.com/production-speakerswire-images/user-profiles/male3x.png","userStat":{"id":1,"followers":4,"followings":5,"broadcastLikes":0,"broadcastViews":90},"name":"satish verma","existingUser":false,"userProfileImageType":"MALE","invitesLeft":4,"userPriviledge":"SW_BROADCASTER"},"description":"satish's Broadcast","streamId":"pub11489928734882","audio":false,"screenShotUrl":"https://ss-api-eb-dev.s3-ap-southeast-1.amazonaws.com/broadcast-images/pub11489928734882-1489928751454.jpg","recordedUrl":"https://production-ss-videos-red5pro.s3-ap-southeast-1.amazonaws.com/video/record/pub581489997130311.mp4","status":"RECORDED","type":"PUBLIC","locationEnabled":false,"commentsEnabled":true,"channel":{"channelId":14,"channel":"Productivity","color":"#4A148C","priority":986,"created":1489922543000,"updated":1489922543000,"broadcast":0,"liveBroadcast":0},"broadcastStat":{"id":4,"likes":0,"views":14,"viewers":5,"liveViewers":0},"latitude":0.0,"longitude":0.0,"startTime":1489928737000,"endTime":1489928787000,"updated":1489928737000,"event":{"id":4,"description":"satish's Broadcast","type":"BROADCAST_PUBLIC","startTime":1489928737000,"endTime":1489928787000,"status":"FINISHED","eventReminderStatus":"NOT_SENT","updatedAt":1489928787000},"expectedDuration":0,"serviceProvider":"agora"}
Update:
broadcastData = {
...broadcast,
broadcaster: {
name: broadcast.user.name,
handle: broadcast.user.handle
},
channel: {
// channelName: broadcast.channel
},
likes: broadcast.broadcastStat.likes,
views: broadcast.broadcastStat.views,
}
Component 1
render() {
return (
<div className="flexslider tabs_slider no-slide">
<ul className="slides">
{this.state.Movies.map((item, index) => <Component2
key={item.db_recom_id}
item={item}
/>)}
</ul>
</div>
)
}
Component 2
render() {
return (
<li>
<img className="wrap_me" src={this.props.item.db_movies_img} />
)
}
Values that you specified in ques, are present directly inside object, you can access them by data.channel.any_key, data.description, data.recordedUrl.
If you want to print all the values of data.channel, then use map otherwise you can access directly by data.channel.channel.
Check this example:
let data = {
"id":4,
"user":{
"userId":1,
"chatUserId":0,
"handle":"satishkrypto",
"countryCode":"+971",
"phone":"569942359",
"picUrl":"https://ss-ap-southeast-1.amazonaws.com/production-speakerswire-images/user-profiles/male3x.png",
"userStat":{
"id":1,
"followers":4,
"followings":5,
"broadcastLikes":0,
"broadcastViews":90
},
"name":"satish verma",
"existingUser":false,
"userProfileImageType":"MALE",
"invitesLeft":4,
"userPriviledge":"SW_BROADCASTER"
},
"description":"satish's Broadcast",
"streamId":"pub11489928734882",
"audio":false,
"screenShotUrl":"https://ss-api-eb-dev.s3-ap-southeast-1.amazonaws.com/broadcast-images/pub11489928734882-1489928751454.jpg",
"recordedUrl":"https://production-ss-videos-red5pro.s3-ap-southeast-1.amazonaws.com/video/record/pub581489997130311.mp4",
"status":"RECORDED",
"type":"PUBLIC",
"locationEnabled":false,
"commentsEnabled":true,
"channel":{
"channelId":14,
"channel":"Productivity",
"color":"#4A148C",
"priority":986,
"created":1489922543000,
"updated":1489922543000,
"broadcast":0,"liveBroadcast":0
},
"broadcastStat":{
"id":4,
"likes":0,
"views":14,
"viewers":5,
"liveViewers":0
},
"latitude":0.0,
"longitude":0.0,
"startTime":1489928737000,
"endTime":1489928787000,
"updated":1489928737000,
"event":{
"id":4,
"description":"satish's Broadcast",
"type":"BROADCAST_PUBLIC",
"startTime":1489928737000,
"endTime":1489928787000,
"status":"FINISHED",
"eventReminderStatus":"NOT_SENT",
"updatedAt":1489928787000
},
"expectedDuration":0,
"serviceProvider":"agora"
};
class App extends React.Component{
render(){
return(
<div>
Channel Details: {Object.keys(data.channel).map(el=>{
return <p>{el}: {data.channel[el]}</p>
})}
Description: {data.description}
RecordedUrl: {data.recordedUrl}
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>
Related
I am using react to build my app and on the post component there are 3 other child components that are been called in a map function while passing the post props.
On the list component when a user clicks on the like button the post tends to reload, and that is not what I want.
This is my post parent component:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
class Posts extends Component {
constructor(props) {
super(props)
this.state = {
sidebaropen: false,
test: '',
posts: []
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.post.posts.length > 0) {
this.setState({ posts: nextProps.post.posts })
console.log('updated')
}
}
componentDidMount() {
this.props.getPosts();
socket.on('posts', data => {
console.log("resiving :" + JSON.stringify(data))
if (Object.keys(this.state.posts).length > 0 && Object.keys(data).length >
0) {
this.setState({ posts: [data[0], ...this.state.posts] })
} else {
this.setState({ posts: data })
}
})
socket.on('id', data => {
console.log(data)
})
console.log('mounted post')
}
}
render(){
const { loading } = this.props.post;
const { posts, } = this.state;
let closebtn
let postContent;
if (posts === null || loading) {
postContent = <Spinner />;
} else {
postContent = <PostFeeds posts={ posts } />;
}
if (this.state.sidebaropen) {
closebtn = <button className='close-toggle-btn' onClick =
{ this.closetoggleclickhandle } />
}
return (
<div className= "post_wrapper" >
<Postsidebar show={ this.state.sidebaropen } />
< div className = "" >
{ postContent }
< /div>
{ closebtn }
<TiPlus className='creat-post-toggle-btn icons' onClick =
{ this.toggleclickhandle } />
</div>
)
}
}
Posts.propTypes = {
getPosts: PropTypes.func.isRequired,
post: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
post: state.post
})
export default connect(mapStateToProps, { getPosts })(Posts);
and this is the first child component
import React, { Component } from 'react';
import PostItem from './PostItem';
class PostFeeds extends Component {
componentDidMount() {
//this.setState({ test : 'mounted'})
console.log('mounted feed')
}
render() {
const { posts } = this.props;
//console.log(posts)
return posts.map(post => <PostItem key={ post._id } post = { post } />);
}
}
postItem.js its i little kind of rough
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { deletePost, addLike, removeLike, bookmark } from "../../actions/postsActions";
import Postimg from './Postimg';
import { MdBookmarkBorder ,/**MdBookmark */} from "react-icons/md";
import {AiFillDislike, AiOutlineLike, AiFillDownSquare} from 'react-icons/ai'
import { TiHeartOutline, TiHeartFullOutline, TiMessage, TiDelete } from "react-icons/ti";
class PostItem extends Component {
onDeleteClick(id){
this.props.deletePost(id);
}
componentWillMount() {
console.log( 'mounted item')
//console.log(window.scrollTo(0, localStorage.getItem('scrollpossition')))
}
onLikeClick(id){
this.props.addLike(id);
// window.scrollTo(0, localStorage.getItem('scrollpossition'))
window.location.href = '/feed'
}
onUnlikeClick(id){
this.props.removeLike(id);
// window.scrollTo(0, localStorage.getItem('scrollpossition'))
window.location.href = '/feed'
}
findUserLike(likes) {
const { auth } = this.props;
if(likes.length > 0){
if(likes.filter(like => like.user === auth.user.id).length > 0) {
return true;
} else {
return false;
}
}
}
findUserDislike(dislikes) {
const { auth } = this.props;
if(dislikes.length > 0){
if(dislikes.filter(dislike => dislike.user === auth.user.id).length > 0) {
return true;
} else {
return false;
}
}
}
onBookmark (id){
this.props.bookmark(id)
}
render() {
const { post, auth, showActions } = this.props;
let ifAlreadyliked;
let ifAlreadydisliked;
let postimg;
let postText;
let profileimg
let topic = ''
if(post.user)
{
if(post.user.profileImageData){
profileimg = <Link to={`/profile/${post.profile.handle}`}><img src={post.profile.profileImageData} alt='' /></Link>
}else{
profileimg = <img src='/assets/images/user-4.png' alt='pip' />
}
if(this.findUserLike(post.likes)){
ifAlreadyliked = <TiHeartFullOutline className= 'icons like-color'/>
}else{
ifAlreadyliked = <TiHeartOutline className= 'icons'/>
}
if(this.findUserDislike(post.dislikes)){
ifAlreadydisliked = <AiFillDislike className= 'icons yellow'/>
}else{
ifAlreadydisliked = <AiOutlineLike className= 'icons' onClick={this.onUnlikeClick.bind(this, post._id)}/>
}
}
if(post.Topic){
topic = <div className= ''><small><b style={{color:'#ff8d00'}}>< AiFillDownSquare />{post.Topic}</b></small></div>
}
if(post.postImageData !== '' && post.postImageData !== null && post.postImageData !== undefined)
{
postimg = <Postimg imageSrc = {post.postImageData} imgAlt = {''}/>
}
if(post.text !== '' || post.text === null)
{
postText = <div className='feed_text'>{post.text}</div>
}
return (
<div className="feed_card">
<div className="feed_header">
<div className="feed-profile-img">{profileimg}</div>
<div className="feed-handle-text">{post.name}</div>
<div className='v-spacer'/>
<div className="time-stamp"><small>{new Date (post.date).toLocaleString ('en-US', {hour: 'numeric', hour12: true, minute: 'numeric', month: 'long', day: 'numeric' } )} </small></div>
</div>
<div className="feed-body-container">
<div>
{topic}
{postimg}
{postText}
<div className='mini_feed_footer'>
<small>{post.likes.length} likes. {post.comments.length} comments. {post.dislikes.length} dislikes.</small>
</div>
{ showActions ? (
<div className='feed_footer'>
<div onClick={this.onLikeClick.bind(this, post._id)} type="button" className="btn btn-light mr-1">
<div className='feed-icon-mini-container'>
{ifAlreadyliked}
</div>
</div>
<div className='spacer'/>
{ifAlreadydisliked}
<div className='spacer'/>
<Link to={`/post/${post._id}`} className='header-brand'>
<TiMessage className='icons'/>
</Link>
<div className='spacer'/>
{ post.user === auth.user.id ? (
<TiDelete
onClick={this.onDeleteClick.bind(this, post._id)}
className="icons red"
/>
) : <MdBookmarkBorder
onClick={this.onBookmark.bind(this, post._id)}
className="icons blue"
/> }
</div>) : null}
</div>
</div>
</div>
);
}
}
PostItem.defaultProps = {
showActions: true
}
PostItem.propTypes = {
post: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired,
deletePost: PropTypes.func.isRequired,
addLike:PropTypes.func.isRequired,
removeLike:PropTypes.func.isRequired,
bookmark:PropTypes.func.isRequired
};
const mapStateToProps = state => ({
auth: state.auth
})
export default connect(mapStateToProps, {deletePost, addLike,bookmark, removeLike})(PostItem);
Don't use window object for navigation (Major) as this causes reload. Make your handlers arrow functions (minor).
onLikeClick = id => {
this.props.addLike(id);
// window.scrollTo(0, localStorage.getItem('scrollpossition'))
this.props.history.push("/feed");
};
onUnlikeClick = id => {
this.props.removeLike(id);
// window.scrollTo(0, localStorage.getItem('scrollpossition'))
this.props.history.push("/feed");
};
Also if /feed is the same page then remove it all together, no need for it.
I have a course page with a list of students as buttons. On click, the button should render ShowStudentInfo but my ShowStudentInfo component is not rendering on click when nested inside (if state.isClicked). Outside of the the conditional it works fine but I need that conditional otherwise everything will show up on course page render.
Main Course Component
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions/index';
import { Redirect } from 'react-router';
import { Link } from 'react-router-dom';
import ShowStudentInfo from '../ShowStudentInfo/ShowStudentInfo'
class CoursePage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
course: {},
student: {},
isClicked: false
};
console.log(this.props.match.params.cuid)
this.onClick = this.onClick.bind(this)
}
onClick(event) {
event.preventDefault()
console.log(this.state.isClicked)
this.setState({
isClicked: !this.state.isClicked
})
}
componentDidMount() {
this.props.dispatch(actions.getCourse(this.props.match.params.cuid));
this.props.dispatch(actions.getStudents());
}
render() {
let studentList = this.props.student
const students = Object.keys(studentList).map(student => studentList[student])
const currentStudents = students.map(student => {
if ((this.props.match.params.cuid) == student.courses) {
return (
<p>
<button className="students" id={student._id} onClick={this.onClick}>{student.firstName} {student.lastName}</button>
</p>
)
if (this.state.isClicked) {
return (
<div className="student-info">
<ShowStudentInfo firstName={student.firstName}
lastName={student.lastName} phoneNumber={student.phoneNumber} />
</div>
)
}
}
})
return (
<div>
<h1>{this.props.course.name}</h1>
<Link to={`/addStudent/${this.props.match.params.cuid}`}> Add a new student</Link>
<div className="studentList">Your students{currentStudents} </div>
</div>
);
}
}
const mapStateToProps = (state, props) => {
return {
course: state.course.course,
student: state.student.students
}
}
export default connect(mapStateToProps)(CoursePage)
My ShowStudentInfo component
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions/index';
import { Redirect } from 'react-router';
import { Link } from 'react-router-dom';
class ShowStudentInfo extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
student: {
firstName: '',
lastName: '',
phoneNumber: ''
},
isClickedEdit: false,
isClickedDelete: false
}
this.isClickedEdit = this.isClickedEdit.bind(this)
this.isClickedDelete = this.isClickedDelete.bind(this)
}
isClickedEdit(event) {
this.setState({
isClickedEdit: true
})
}
isClickedDelete(event) {
this.setState({
isClickedDelete: true
})
}
render() {
return (
<div className="student-info-container">
<p>Name: {this.props.firstName} {this.props.lastName}</p>
<p>Phone Number: {this.props.phoneNumber}</p>
</div>
)
}
}
if (this.state.isClicked) {
return (
<div className="student-info">
<ShowStudentInfo firstName={student.firstName}
lastName={student.lastName} phoneNumber={student.phoneNumber} />
</div>
)
}
is the most important part to look at and the info is rendering normally without the onClick conditional.
Your map function contains 2 return functions, while the first return will cause it to go to the next item in the current iteration process
if ((this.props.match.params.cuid) == student.courses) {
return (
<p>
<button className="students" id={student._id} onClick={this.onClick}>{student.firstName} {student.lastName}</button>
</p>
)
// this will never hit in case the previous statement is evaluates to true
if (this.state.isClicked) {
return (
<div className="student-info">
<ShowStudentInfo firstName={student.firstName}
lastName={student.lastName} phoneNumber={student.phoneNumber} />
</div>
)
}
}
To achieve what you want to do, (i am guessing you wish it as part of the first return statement), you could do it like so
if ((this.props.match.params.cuid) == student.courses) {
return (
<p>
<button className="students" id={student._id} onClick={this.onClick}>{student.firstName} {student.lastName}</button>
{ this.state.isClicked && <div className="student-info">
<ShowStudentInfo firstName={student.firstName}
lastName={student.lastName} phoneNumber={student.phoneNumber} />
</div> }
</p>
)
}
Be warned: This will show the students info as part of the p tag for all the students on the screen, I don't see where you restrict showing the users info for the one clicked student.
As another side note, are you sure you wish to comparse an object of courses with a cuid parameter?
This is just a little refactoring in your logic :) hope it helps you.
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions/index';
import { Redirect } from 'react-router';
import { Link } from 'react-router-dom';
import ShowStudentInfo from '../ShowStudentInfo/ShowStudentInfo'
class CoursePage extends React.Component {
state = {
course: {},
student: {},
isClicked: false
};
onClick = (event) => {
event.preventDefault()
console.log(this.state.isClicked)
this.setState({
isClicked: !this.state.isClicked
})
}
getCurrentStudents = (students) => {
const { match } = this.props
const { isClicked } = this.state
return students.map(student => {
if (match.params.cuid == student.courses) {
return (
<div>
<p><button className="students" id={student._id} onClick={this.onClick}>
{student.firstName} {student.lastName}
</button></p>
{isClicked && this.getStudentInfo(student) }
</div>
)
}
})
}
getStudentInfo = (student) => (
<div className="student-info" >
<ShowStudentInfo
firstName={student.firstName}
lastName={student.lastName}
phoneNumber={student.phoneNumber} />
</div>
)
componentDidMount() {
let { match, dispatch } = this.props
dispatch(actions.getCourse(match.params.cuid));
dispatch(actions.getStudents());
}
render() {
let { studentList, match, course } = this.props
const students = Object.keys(studentList).map(student => studentList[student])
const currentStudents = this.getCurrentStudents(students)
return (
<div>
<h1>{course.name}</h1>
<Link to={`/addStudent/${match.params.cuid}`}> Add a new student</Link>
<div className="studentList">Your students{currentStudents} </div>
</div>
);
}
}
const mapStateToProps = (state, props) => {
return {
course: state.course.course,
student: state.student.students
}
}
export default connect(mapStateToProps)(CoursePage)
I am trying to redirect to the index route from "mypolls" page.
The problem is when I click the logout button in the header it redirects to the path of the first Link component in my list
import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
class PollsList extends Component {
static contextTypes = {
router: PropTypes.object
};
componentWillMount() {
this.props.fetchPolls();
}
componentWillReceiveProps(nextProps) {
const { authenticatedUser, type } = nextProps;
if (!authenticatedUser && type === 'mypolls') {
this.context.router.push('/');
}
}
componentWillUnmount() {
//Important! If your component is navigating based on some global state(from say componentWillReceiveProps)
//always reset that global state back to null when you REMOUNT
this.props.resetMe();
}
renderOptions(options) {
return options.map(o => {
o = o.trim();
return (
<span className="list-group-item-text">{" " + o + " "}</span>
);
});
}
renderPolls(polls) {
const { type, authenticatedUser, user } = this.props;
if (authenticatedUser) {
if (type === 'mypolls') {
return polls.filter(poll => user.user._id === poll.authorId)
.map((poll) => {
return (
<li className="list-group-item" key={poll._id}>
<Link style={{color:'black'}} to={"polls/" + poll._id}>
// example redirect: http://localhost:8080/polls/586e0d06eedc57071566b1f2
<h3 className="list-group-item-heading">{poll.title}</h3>
</Link>
{this.renderOptions(poll.options)}
</li>
);
});
}
}
return polls.map((poll) => {
return (
<li className="list-group-item" key={poll._id}>
<Link style={{color:'black'}} to={"polls/" + poll._id}>
<h3 className="list-group-item-heading">{poll.title}</h3>
</Link>
{this.renderOptions(poll.options)}
</li>
);
});
}
render() {
const { polls, loading, error } = this.props.pollsList;
if (loading) {
return <div className="container"><h1>Polls</h1><h3>Loading...</h3></div>
} else if (error) {
return <div className="alert alert-danger">Error: {error.message}</div>
}
return (
<div className="container">
<div className="col-md-6 col-md-offset-3">
<h1>Polls</h1>
<ul className="list-group">
{this.renderPolls(polls)}
</ul>
</div>
</div>
);
}
}
export default PollsList;
The Header.js component also is set to redirect if the user is logged out
componentWillReceiveProps(nextProps) {
if (nextProps.deletedPoll.error && nextProps.deletedPoll.error.message) {//delete failure
alert(nextProps.deletedPoll.error.message || 'Could not delete. Please try again.');
} else if (nextProps.deletedPoll.poll && !nextProps.deletedPoll.error) {//delete success
this.context.router.push('/');
} else if (this.props.user.user && !nextProps.user.user) {//logout (had user(this.props.user.user) but no loger the case (!nextProps.user.user))
this.context.router.push('/');
}
}
Here is the container component
import { connect } from 'react-redux'
import { fetchPolls, fetchPollsSuccess, fetchPollsFailure, resetPolls } from '../actions/polls';
import PollsList from '../components/PollsList';
const mapStateToProps = (state) => {
return {
pollsList: state.polls.pollsList,
user: state.user,
status: state.user.status,
authenticatedUser: state.user.status === 'authenticated' ? state.user.user : null
};
}
const mapDispatchToProps = (dispatch) => {
return {
fetchPolls: () => {
dispatch(fetchPolls()).then((response) => {
!response.error ? dispatch(fetchPollsSuccess(response.payload.data)) : dispatch(fetchPollsFailure(response.payload.data));
});
},
resetMe: () => {
dispatch(resetPolls());
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(PollsList);
I'm new in React and I'm using Semantic-ui-react. I'm trying to use the Dropdown.
When I want to get my value from the dropdown and call my function. My event get some proxy object.
handleTagChange(e) {
console.log("handleTagChange");
console.log(e);
}
But if I add something else like test in the function, the e.target.value works and test is the proxy object. Why is that?
handleTagChange(test, e) {
console.log("handleTagChange");
console.log(test);
console.log(e);
}
TagFilter.js
import React, { PropTypes } from 'react';
import { Dropdown } from 'semantic-ui-react'
export default class TagFilter extends React.PureComponent {
render() {
console.log(this.props);
const options = [
{ "text": "Admin stuff", "value": "admin stuff" },
{ "text": "Frontend", "value": "frontend" },
{ "text": "JS", "value": "js" },
{ "text": "Mucking about", "value": "mucking about" },
{ "text": "React", "value": "react" }
];
return (
<Dropdown placeholder='Skills' fluid selection options={options} onChange={this.props.handleTagChange} />
);
}
}
Employee.js
import React, { PropTypes } from 'react';
import { Image, List } from 'semantic-ui-react';
import TagFilter from './TagFilter';
import ProductFilter from './ProductFilter';
import MyModal from './Modal';
export default class Employees extends React.Component {
//static defaultProps = {
//}
constructor() {
super();
this.closeModal = this.closeModal.bind(this);
this.handleTagChange = this.handleTagChange.bind(this);
this.handleProductChange = this.handleProductChange.bind(this);
}
state = {
tagsFilterValue: null,
productsFilterValue: null,
employeeDetails: null,
openModal: false
}
handleTagChange(e) {
console.log("handleTagChange");
console.log(e);
}
handleProductChange(e) {
let productValue = e.target.value;
this.setState({productsFilterValue: productValue});
}
handleEmployeeClick(name, e) {
this.setState({employeeDetails: name});
this.setState({openModal: true});
}
closeModal() {
this.setState({openModal: false});
}
render() {
let filteredEmployees = this.props.data.filter(
(employee) => {
// If state tagsFilterValue and productsFilterValue is not null
if (this.state.tagsFilterValue && this.state.productsFilterValue) {
return employee.tags.indexOf(this.state.tagsFilterValue) !== -1 && employee.products.indexOf(this.state.productsFilterValue) !== -1;
}
// If state tagsFilterValue is not null
else if (this.state.tagsFilterValue) {
return employee.tags.indexOf(this.state.tagsFilterValue) !== -1;
}
// If state productsFilterValue is not null
else if (this.state.productsFilterValue) {
return employee.products.indexOf(this.state.productsFilterValue) !== -1;
}
else {
return employee;
}
}
);
let employeeDetails = this.props.data.filter(
(employee) => {
return employee.name.indexOf(this.state.employeeDetails) !== -1;
}
);
return (
<div>
{ employeeDetails.map((employee) => (
<MyModal employeeDetails={employee} closeModal={this.closeModal} openModal={this.state.openModal} />
))}
<div className="ui grid">
<TagFilter handleTagChange={this.handleTagChange} tagsFilterValue={this.state.tagsFilterValue} />
<ProductFilter handleProductChange={this.handleProductChange} productsFilterValue={this.state.productsFilterValue} />
</div>
<List>
{ filteredEmployees.map((employee) => (
<List.Item key={employee.name}>
<div className="ui card">
<div className="image">
<img alt="User avatar" src={employee.image}/>
</div>
<div className="content">
<a className="header" onClick={this.handleEmployeeClick.bind(this, employee.name)}>{employee.name}</a>
<div className="meta">{employee.title}</div>
</div>
</div>
</List.Item>
))}
</List>
</div>
);
}
}
This is happening because most semantic-ui-react events return 2 objects, and the second one is what contains the data that you need to handle the event.
There's a more detailed explanation in a GitHub issue here:
https://github.com/Semantic-Org/Semantic-UI-React/issues/638#issuecomment-252035750
I moved away from Alt to Redux and decided to take advantage of context type.
Somewhere in the mix, my ref is now undefined.
What would be the proper procedure for refs to be available with this code:
import React, { Component, PropTypes } from 'react';
// components
import TopNavMenuItem from './top-nav-menu-item';
export default class TopNavZone extends Component {
fetchMenu() {
const results = [];
const navItems = this.context.navItems;
navItems.map((item, index) => {
results.push(
<TopNavMenuItem key={ index }
clientId={ this.context.clientInfo._id }
item={ item }
index={ index }
parent={ this.refs.topNavList }
/>
);
});
return results;
}
render() {
return (
<section>
<nav className="top-nav" id="TopNavZone">
<ul ref="topNavList" className="">
{ this.fetchMenu() }
</ul>
</nav>
</section>
);
}
}
TopNavZone.contextTypes = {
navItems: PropTypes.array.isRequired,
clientInfo: PropTypes.object.isRequired
};
Thank you all.
I captured the ref in ComponentDidMount and made the data part of state instead of calling the function this.fetchMenu from render:
import React, { Component, PropTypes } from 'react';
// components
import TopNavMenuItem from './top-nav-menu-item';
export default class TopNavZone extends Component {
constructor(props) {
super(props); {
this.state = {
results: null
}
}
}
componentDidMount() {
var topNavList = this.refs.topNavList;
this.setState({ results: this.fetchMenu(topNavList) })
}
fetchMenu(topNavList) {
const results = [];
const items = this.context.navItems;
items.map((item, index) => {
results.push(
<TopNavMenuItem key={ index }
clientId={ this.context.clientInfo._id }
item={ item }
index={ index }
parent={ topNavList }
/>
);
});
return results;
}
render() {
return (
<section>
<nav className="top-nav" id="TopNavZone">
<ul ref="topNavList" className="">
{ this.state.results }
</ul>
</nav>
</section>
);
}
}
TopNavZone.contextTypes = {
navItems: PropTypes.array.isRequired,
clientInfo: PropTypes.object.isRequired
};