I'm trying to print an objects value by not its own key but a string similar to the key. I somehow got the key match using filter function from the useParams() string, just one more step remaining for my desired output.
import React from 'react';
import { useParams } from 'react-router-dom';
function MoreArticle() {
const feed = {
Fall : 'This is the Detailed description about season of Fall',
Summer : 'This is the Detailed description about season Summer',
Winter : 'This is the Detailed description about season Winter',
Monsoon : 'This is the Detailed description about season Monsoon',
Spring : 'This is the Detailed description about season Spring',
};
const { name } = useParams(); //Summer
const seasons = Object.keys(feed);
return (
<div>
<div>
{seasons.filter(season => {
console.log(feed.season);
return(
season == name && <div>{season}</div> //Returns Summer
//season == name && <div>{feed.season}</div>
//How to return object description 👆🏻
//by using something like this value |
);
})}
</div>
</div>
);
}
export default MoreArticle;
Instead of using feed.season, consider using the bracket notation to target a specific key value pair, like this: feed[name]
import React from 'react';
import { useParams } from 'react-router-dom';
function MoreArticle() {
const feed = {
Fall : 'This is the Detailed description about season of Fall',
Summer : 'This is the Detailed description about season Summer',
Winter : 'This is the Detailed description about season Winter',
Monsoon : 'This is the Detailed description about season Monsoon',
Spring : 'This is the Detailed description about season Spring',
};
const { name } = useParams(); //Summer
return (
<div>{feed[name]}</div>
);
}
export default MoreArticle;
See more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors
Related
I have a failing test but can't work out why. I have react-router links which link to the URL structure: /classes/${weekday}.
Classes component then sets the activeWeekday in context by React Router location which is displayed by the Classes as {activeWeekday} Classes
Functionality works i nthe browser, but for some reason in my tests it's not updating the header so the test is failing.
TestingLibraryElementError: Unable to find an element with the text: /friday classes/i
Can anyone see why? I can't figure it out.
Thks so much in advance.
Update - Here is a codepen replicating the issue.
// Snapshot of the state passed to Classes via context
export const ClassesProvider = ({ children }: ClassesProviderProps) => {
const [activeWeekdayNumber, setActiveWeekdayNumber] = useState<number>(
new Date().getDay()
);
// Classes component
const Classes = () => {
const { activeWeekdayNumber, setActiveWeekdayNumber } = useContext(ClassesContext);
const location = useLocation();
useEffect(() => {
const day = location.pathname.replace("/classes/", "");
const dayIndex = daysOfWeekArray.indexOf(capitaliseFirstLetter(day));
if (dayIndex !== -1) {
setActiveWeekdayNumber(
daysOfWeekArray.indexOf(capitaliseFirstLetter(day))
);
}
}, [location, setActiveWeekdayNumber]);
return (
<>
<h2>{daysOfWeekArray[activeWeekdayNumber]} Classes</h2>
</>
);
};
// failing test - TestingLibraryElementError: Unable to find an element with the text: /friday classes/i
const setup = (value: ClassesContextType) =>
render(
<ClassesContext.Provider value={value}>
<MemoryRouter>
<Classes />
</MemoryRouter>
</ClassesContext.Provider>
);
test("displays the relevant heading when a day of the week link is clicked", () => {
const value = {
activeWeekdayNumber: 3, // wednesday
};
setup(value);
const link = screen.getByRole("link", { name: "Friday" });
fireEvent.click(link);
expect(screen.getByText(/friday classes/i)).toBeInTheDocument();
});
});
The menu list is a styled link:
<li>
<HorizontalMenuLink $active={weekdayNumber === 1} to="/classes/monday">
Monday
</HorizontalMenuLink>
</li>
I'm changing an attribute of a Lit web component, but the changed value won't render.
I have an observed array: reports[] that will be populated in firstUpdated() with reports urls fetched from rest apis. The loading of the array is done by:
this.reports.push({ "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" });
see below:
import { LitElement, html, css } from 'lit';
import {apiUrl, restApiUrl} from '../../config';
export default class Homepage extends LitElement {
static properties = {
apiUrl: '',
restApiUrl: '',
reports: []
}
...
constructor() {
super();
this.apiUrl = apiUrl;
this.restApiUrl= restApiUrl;
this.reports = [];
}
firstUpdated() {
...
// Fetch all reports from restApiUrl:
rsAPIDetails(restApiUrl).then(reports =>{
for(const report of reports.value)
{
rsAPIDetails(restApiUrl + "(" + report.Id + ")/Policies").then(policies => {
for(const policy of policies.Policies)
{
if(policy.GroupUserName.endsWith(usernamePBI))
{
for(const role of policy.Roles)
{
if(role != null && (role.Name== "Browser" || role.Name== "Content Manager"))
{
// User has access to this report so i'll push it to the list of reports that will show in the navbar:
this.reports.push({ "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" });
}
}
}
}
});
}
}).then(q => {
console.log(this.reports);
});
}
render() {
return html`
<div id="sidenav" class="sidenav">
...
<div class="menucateg">Dashboards</div>
${this.reports.map((report) =>
html`<a #click=${() => this.handleMenuItemClick(report.url)}>${report.name}</a>`
)}
<div class="menucateg">Options</div>
</div>
`;
}
At console I can clearly see that the array is loaded with the correct values.
But the render() function won't update the web component with the new values of reports[]:
The links should be added inside 'Dashboards' div
If instead I statically populate reports[] with values (in the ctor), it renders the links just fine.
So why isn't the component updated when the observed array is changed ?
Thank you!
Array.push mutates the array, but doesn't change the actual value in memory.
To have LitElement track updates to arrays and objects, the update to the value needs to be immutable.
For example, we can make your example work by doing it this way:
const newReports = this.reports.slice();
newReports.push({ "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" });
this.reports = newReports;
Or by using array spread
this.reports = [...this.reports, { "name" : report.Name, "url" : this.apiUrl + "/" + report.Name + "?rs:embed=true" }]
The reason why this works is that when you do this.reports.push(), you're not actually changing the "reference" of this.reports, you're just adding an object to it. On the other hand, when you re-define the property with this.reports = ..., you are changing the "reference", so LitElement knows the value has changed, and it will trigger a re-render.
This is also true for objects. Let's say you have a property obj. If you updated the object by just adding a property to, the element wouldn't re-render.
this.obj.newProp = 'value';
But if you re-define the object property as a whole by copying the object and adding a property, it will cause the element to update properly.
this.obj = {...this.obj, newProp: 'value'}
You can see the values that are getting tracked and updated by using the updated method.
In here i want to get a date from the SharePoint list and set it in the datepicker,
enter image description here
FYI the date is coming properly from the API , i am using pnp js to retrieve data, but only the date value is not setting into the datepicker
#Sandesh Rathnayake,
This control has exposed a property to set its value:
https://developer.microsoft.com/en-us/fluentui#/controls/web/datepicker#implementation
You can define a Date varible in the state of react componment then set its value as below:
export class DatePickerBasicExample extends React.Component<any, IDatePickerBasicExampleState> {
constructor() {
super();
this.state = {
firstDayOfWeek: DayOfWeek.Sunday,
value: new Date()
};
}
....
<DatePicker
label='Start date'
isRequired={ false }
allowTextInput={ true }
ariaLabel={ desc }
firstDayOfWeek={ this.state.firstDayOfWeek }
strings={ DayPickerStrings }
value={ this.state.value }
onSelectDate={ date => this.setState({ value: date }) }
/>
You could use the "minDate" attr of the datepicker.
<DatePicker
label='Start date'
isRequired={ false }
allowTextInput={ true }
ariaLabel={ desc }
firstDayOfWeek={ this.state.firstDayOfWeek }
strings={ DayPickerStrings }
minDate={new Date()}
value={ this.state.value }
onSelectDate={ date => this.setState({ value: date }) }
/>
static async getInitialProps() {
const campaigns = await factory.methods.getDeployedCampaigns().call();
const campaign = Campaign(campaigns[0]);//call the contract to be able to use the methods inside the campaign
const summary = await campaign.methods.getSummary().call();
return { campaigns,summary };//campaigns is given to campaignIndex as an object
}
renderCampaigns() {
const items = this.props.campaigns.map(address => {
return {
header: this.props.summary[7] ,
description:(
<Segment >
<Progress percent={this.props.summary[1]/this.props.summary[6]} attached='bottom' success/>
<Card.Content description = {'balance: '+ web3.utils.fromWei(this.props.summary[1], 'ether') + ' ' + 'ether'} textAlign='right'/>
</Segment>
),
extra:(
<Link route={`/campaigns/${address}`}>
<a>View Campaign</a>
</Link>
),
fluid: true,//card takes width of the container
//percentage goal of the event),
link: true,
meta:(
<Segment>
<Card.Content header ={'Description: '+ this.props.summary[5]} textAlign='left'/>
<Card.Content description = {'Goal: '+ this.props.summary[6] +' wei'} textAlign='left'/>
</Segment>
)
};
});
So my problem is that I want to go through an array of string provided by campaigns and pass each string to my function campaign and just after that be able to call the methods found in the class campaign through summary. Since summary is an await function my loop needs to be an async loop.I have tried to
create an array of objects in which in the mapping of the string I push all the data from my summary array in it but I get an out of scope error from which it says that my mapping is not async.Snippet of my actual code I just want to get an idea how to create an async function in which I can map all the strings from campaigns in it get my data from summary and return an array of data to render below
I'm trying to process an utterance in the format "Get News from Impeachment Sage" where Impeachment Sage corresponds to an enum of publication names. Bixby is successfully understanding the utterance and trying to call my goal (GetNewsByName) but the trained Value is not arriving at the function. (This is based off the user persistence data example).
The operative portion of the function is thus:
function getNewsByName(altBrainsNames) {
// const name = "Impeachment Sage" //hard coded for testing
const url = properties.get("config", "baseUrl") + "altbrains"
console.log("i got to restdb.js and the url is ", url);
console.log("AltBrainsNames is", altBrainsNames)
const query = {
apikey: properties.get("secret", "apiKey"),
q: "{\"" + "name" + "\":\"" + name + "\"}"
// q: "{}"
}
console.log("query", query)
const options = {
format: "json",
query: query,
cacheTime: 0
}
const response = http.getUrl(url, options)
if (response) {
const content1 = response
// const altBrainsData = response[0][properties.get("config", "altbrainsName")]
// altbrainsData.$id = response[0]["_id"]
console.log('content1', content1);
console.log('identifier', content1)
return content1
} else {
// Doesn't exist
console.log('doesnae exist');
return
}
}
What is happening here where the Value is not reaching the function?
The Action model is:
action (GetNewsByName) {
description ("Get news data from remote Content db by searching on AltBrain name")
type (Calculation)
output (Content)
collect {
input (altBrainsNames) {
type (AltBrainsNames)
min (Required) max (One) //this means js must catch error when multiple names offered
}
}
}
We resolved this offline, just wanted to follow up on the public channel to any fellow Bixby developers seeing this question posted. The function that calls 'getNewsByName' needs to receive the input parameter. Once populated, the action worked successfully.